dskcode 0.1.1 → 0.1.3
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.md +4 -3
- package/dist/index.js +908 -3
- package/dist/index.js.map +1 -1
- package/package.json +5 -1
package/README.md
CHANGED
|
@@ -19,6 +19,7 @@
|
|
|
19
19
|
- **权限控制** — 三级审批策略(Allow / Ask / Deny),安全可控
|
|
20
20
|
- **TOML 配置** — 多层级配置(全局 + 项目 + 环境变量 + CLI flag)
|
|
21
21
|
- **中文优先** — 界面提示、帮助信息、文档均为中文
|
|
22
|
+
- **内置小游戏** — `dskcode game` 启动游戏列表,打砖块等内置游戏供休闲娱乐
|
|
22
23
|
|
|
23
24
|
## 快速开始
|
|
24
25
|
|
|
@@ -48,6 +49,7 @@ npx dskcode chat
|
|
|
48
49
|
| `dskcode run <prompt>` | 执行一次性任务(如"修改所有 TODO") |
|
|
49
50
|
| `dskcode setup` | 运行配置向导,设置 API Key 等 |
|
|
50
51
|
| `dskcode init` | 在当前项目生成 AGENTS.md 项目记忆文件 |
|
|
52
|
+
| `dskcode game <name>` | 启动内置小游戏,不指定名称则显示交互式游戏列表 |
|
|
51
53
|
| `dskcode completion` | 生成 shell 自动补全配置 |
|
|
52
54
|
|
|
53
55
|
### 全局选项
|
|
@@ -104,9 +106,8 @@ src/
|
|
|
104
106
|
## 开发
|
|
105
107
|
|
|
106
108
|
```bash
|
|
107
|
-
#
|
|
108
|
-
git clone https://github.com/
|
|
109
|
-
cd ts-version
|
|
109
|
+
# 克隆仓库(clone 后直接安装即可)
|
|
110
|
+
git clone https://github.com/Awu12277/deepseek-agent-cli.git
|
|
110
111
|
|
|
111
112
|
# 安装依赖
|
|
112
113
|
npm install
|
package/dist/index.js
CHANGED
|
@@ -214,9 +214,870 @@ function ChatSession({ providerCount, toolCount, verbose }) {
|
|
|
214
214
|
] });
|
|
215
215
|
}
|
|
216
216
|
|
|
217
|
+
// src/ui/GamePicker.tsx
|
|
218
|
+
import { Box as Box4, Text as Text5, useInput } from "ink";
|
|
219
|
+
import { useState as useState3, useCallback as useCallback2 } from "react";
|
|
220
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
221
|
+
function GamePicker({ games, onSelect, onExit }) {
|
|
222
|
+
const [selectedIndex, setSelectedIndex] = useState3(0);
|
|
223
|
+
useInput(
|
|
224
|
+
useCallback2(
|
|
225
|
+
(input, key) => {
|
|
226
|
+
if (games.length === 0) return;
|
|
227
|
+
if (key.upArrow || input === "k") {
|
|
228
|
+
setSelectedIndex((prev) => prev > 0 ? prev - 1 : games.length - 1);
|
|
229
|
+
} else if (key.downArrow || input === "j") {
|
|
230
|
+
setSelectedIndex((prev) => prev < games.length - 1 ? prev + 1 : 0);
|
|
231
|
+
} else if (key.return) {
|
|
232
|
+
const game = games[selectedIndex];
|
|
233
|
+
if (game) onSelect(game);
|
|
234
|
+
} else if (key.escape || input === "q") {
|
|
235
|
+
onExit();
|
|
236
|
+
}
|
|
237
|
+
},
|
|
238
|
+
[games, selectedIndex, onSelect, onExit]
|
|
239
|
+
)
|
|
240
|
+
);
|
|
241
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "column", children: [
|
|
242
|
+
/* @__PURE__ */ jsx4(Box4, { marginBottom: 1, children: /* @__PURE__ */ jsx4(Text5, { bold: true, color: "#00ffff", children: "\u{1F3AE} \u6E38\u620F\u5217\u8868" }) }),
|
|
243
|
+
/* @__PURE__ */ jsx4(Box4, { flexDirection: "column", children: games.map((game, index) => {
|
|
244
|
+
const isSelected = index === selectedIndex;
|
|
245
|
+
return /* @__PURE__ */ jsxs4(Box4, { flexDirection: "row", children: [
|
|
246
|
+
/* @__PURE__ */ jsx4(Box4, { width: 3, flexShrink: 0, children: isSelected ? /* @__PURE__ */ jsx4(Text5, { bold: true, color: "#00ff41", children: "\u25B8 " }) : /* @__PURE__ */ jsx4(Text5, { children: " " }) }),
|
|
247
|
+
/* @__PURE__ */ jsx4(Box4, { width: 20, flexShrink: 0, children: /* @__PURE__ */ jsx4(Text5, { bold: true, color: isSelected ? "#00ff41" : "#ffffff", children: game.name }) }),
|
|
248
|
+
/* @__PURE__ */ jsx4(Box4, { children: /* @__PURE__ */ jsx4(Text5, { color: "#888888", children: game.description }) })
|
|
249
|
+
] }, game.id);
|
|
250
|
+
}) }),
|
|
251
|
+
/* @__PURE__ */ jsx4(Box4, { marginTop: 1, children: /* @__PURE__ */ jsx4(Text5, { dimColor: true, children: " \u2191/\u2193 \u9009\u62E9 Enter \u542F\u52A8 q \u8FD4\u56DE" }) })
|
|
252
|
+
] });
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// src/game/index.ts
|
|
256
|
+
var registry = /* @__PURE__ */ new Map();
|
|
257
|
+
function registerGame(game) {
|
|
258
|
+
registry.set(game.id, game);
|
|
259
|
+
}
|
|
260
|
+
function getGame(id) {
|
|
261
|
+
return registry.get(id);
|
|
262
|
+
}
|
|
263
|
+
function listGames() {
|
|
264
|
+
return Array.from(registry.values());
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
// src/game/brick-breaker/index.tsx
|
|
268
|
+
import { Box as Box5, Text as Text6, useInput as useInput2, render as render2 } from "ink";
|
|
269
|
+
import { useState as useState4, useEffect as useEffect3, useRef, useCallback as useCallback3 } from "react";
|
|
270
|
+
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
271
|
+
var GAME_WIDTH = 40;
|
|
272
|
+
var GAME_HEIGHT = 18;
|
|
273
|
+
var PADDLE_WIDTH = 9;
|
|
274
|
+
var BRICK_COLORS = [166, 214, 76, 69];
|
|
275
|
+
var LEVELS = [
|
|
276
|
+
{ rows: 4, cols: 8, bw: 3, desc: "\u7ECF\u5178 4\xD78", pattern: () => true },
|
|
277
|
+
{ rows: 3, cols: 8, bw: 3, desc: "\u8F7B\u677E 3 \u5C42", pattern: () => true },
|
|
278
|
+
{ rows: 6, cols: 8, bw: 3, desc: "\u539A\u5899 6 \u5C42", pattern: () => true },
|
|
279
|
+
{ rows: 4, cols: 8, bw: 3, desc: "\u68CB\u76D8\u683C", pattern: (c, r) => (c + r) % 2 === 0 },
|
|
280
|
+
{ rows: 4, cols: 8, bw: 3, desc: "\u91D1\u5B57\u5854", pattern: (c, r, _, tc) => c >= r && c < tc - r },
|
|
281
|
+
{ rows: 4, cols: 8, bw: 3, desc: "\u4EA4\u9519\u6392\u5217", pattern: (c, r) => r % 2 === 0 || c >= 1 && c <= 6 },
|
|
282
|
+
{ rows: 4, cols: 8, bw: 3, desc: "\u4E2D\u7A7A\u8FB9\u6846", pattern: (c, r, tr, tc) => r === 0 || r === tr - 1 || c === 0 || c === tc - 1 },
|
|
283
|
+
{ rows: 4, cols: 10, bw: 2, desc: "\u5BC6\u96C6 10 \u5217", pattern: () => true },
|
|
284
|
+
{ rows: 7, cols: 8, bw: 3, desc: "\u9AD8\u5899 7 \u5C42", pattern: () => true },
|
|
285
|
+
{ rows: 8, cols: 8, bw: 3, desc: "\u6EE1\u5C4F 8 \u5C42", pattern: () => true }
|
|
286
|
+
];
|
|
287
|
+
function getLevel(level) {
|
|
288
|
+
return LEVELS[(level - 1) % LEVELS.length];
|
|
289
|
+
}
|
|
290
|
+
function createBricks(level) {
|
|
291
|
+
const def = getLevel(level);
|
|
292
|
+
const bricks = [];
|
|
293
|
+
const gap = 2;
|
|
294
|
+
const totalW = def.cols * def.bw + (def.cols - 1) * gap;
|
|
295
|
+
const startX = Math.floor((GAME_WIDTH - totalW) / 2);
|
|
296
|
+
const step = def.bw + gap;
|
|
297
|
+
for (let row = 0; row < def.rows; row++) {
|
|
298
|
+
for (let col = 0; col < def.cols; col++) {
|
|
299
|
+
if (def.pattern(col, row, def.rows, def.cols)) {
|
|
300
|
+
bricks.push({
|
|
301
|
+
x: startX + col * step,
|
|
302
|
+
y: 2 + row * 2,
|
|
303
|
+
w: def.bw,
|
|
304
|
+
alive: true
|
|
305
|
+
});
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
return bricks;
|
|
310
|
+
}
|
|
311
|
+
function createInitialState(level) {
|
|
312
|
+
const def = getLevel(level);
|
|
313
|
+
const totalW = def.cols * def.bw + (def.cols - 1) * 2;
|
|
314
|
+
const startX = Math.floor((GAME_WIDTH - totalW) / 2);
|
|
315
|
+
return {
|
|
316
|
+
level,
|
|
317
|
+
bricks: createBricks(level),
|
|
318
|
+
paddleX: Math.floor(GAME_WIDTH / 2) - Math.floor(PADDLE_WIDTH / 2),
|
|
319
|
+
ball: { x: GAME_WIDTH / 2, y: GAME_HEIGHT - 3 },
|
|
320
|
+
ballDir: { x: 1, y: -1 },
|
|
321
|
+
score: 0,
|
|
322
|
+
lives: 3,
|
|
323
|
+
gameOver: false,
|
|
324
|
+
win: false,
|
|
325
|
+
paused: false
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
function update(state) {
|
|
329
|
+
if (state.paused || state.gameOver || state.win) return;
|
|
330
|
+
state.ball.x += state.ballDir.x;
|
|
331
|
+
state.ball.y += state.ballDir.y;
|
|
332
|
+
if (state.ball.x <= 0) {
|
|
333
|
+
state.ball.x = 0;
|
|
334
|
+
state.ballDir.x = 1;
|
|
335
|
+
}
|
|
336
|
+
if (state.ball.x >= GAME_WIDTH - 1) {
|
|
337
|
+
state.ball.x = GAME_WIDTH - 1;
|
|
338
|
+
state.ballDir.x = -1;
|
|
339
|
+
}
|
|
340
|
+
if (state.ball.y <= 0) {
|
|
341
|
+
state.ball.y = 0;
|
|
342
|
+
state.ballDir.y = 1;
|
|
343
|
+
}
|
|
344
|
+
if (state.ball.y === GAME_HEIGHT - 1 && state.ball.x >= state.paddleX && state.ball.x <= state.paddleX + PADDLE_WIDTH) {
|
|
345
|
+
state.ballDir.y = -1;
|
|
346
|
+
const hitPos = (state.ball.x - state.paddleX) / PADDLE_WIDTH;
|
|
347
|
+
state.ballDir.x = hitPos < 0.5 ? -1 : 1;
|
|
348
|
+
}
|
|
349
|
+
if (state.ball.y > GAME_HEIGHT) {
|
|
350
|
+
state.lives--;
|
|
351
|
+
if (state.lives <= 0) {
|
|
352
|
+
state.gameOver = true;
|
|
353
|
+
} else {
|
|
354
|
+
state.ball = { x: GAME_WIDTH / 2, y: GAME_HEIGHT - 3 };
|
|
355
|
+
state.ballDir = { x: 1, y: -1 };
|
|
356
|
+
state.paddleX = Math.floor(GAME_WIDTH / 2) - Math.floor(PADDLE_WIDTH / 2);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
const hitBrick = state.bricks.find((b) => {
|
|
360
|
+
if (!b.alive) return false;
|
|
361
|
+
return state.ball.x >= b.x && state.ball.x < b.x + b.w && state.ball.y >= b.y && state.ball.y < b.y + 1;
|
|
362
|
+
});
|
|
363
|
+
if (hitBrick) {
|
|
364
|
+
hitBrick.alive = false;
|
|
365
|
+
state.score += 10;
|
|
366
|
+
state.ballDir.y = -state.ballDir.y;
|
|
367
|
+
}
|
|
368
|
+
if (state.bricks.every((b) => !b.alive)) state.win = true;
|
|
369
|
+
}
|
|
370
|
+
function buildBoard(state) {
|
|
371
|
+
const lines = [];
|
|
372
|
+
function brickColorIndex(x, y) {
|
|
373
|
+
const row = Math.floor((y - 2) / 2);
|
|
374
|
+
if (row >= 0) {
|
|
375
|
+
const b = state.bricks.find((br) => br.y === y && br.alive && x >= br.x && x < br.x + br.w);
|
|
376
|
+
if (b) return row % BRICK_COLORS.length;
|
|
377
|
+
}
|
|
378
|
+
return void 0;
|
|
379
|
+
}
|
|
380
|
+
for (let y = 0; y < GAME_HEIGHT; y++) {
|
|
381
|
+
let line = "";
|
|
382
|
+
for (let x = 0; x < GAME_WIDTH; x++) {
|
|
383
|
+
const isBall = state.ball.x === x && state.ball.y === y;
|
|
384
|
+
const isPaddle = y === GAME_HEIGHT - 1 && x >= state.paddleX && x < state.paddleX + PADDLE_WIDTH;
|
|
385
|
+
const brickRow = brickColorIndex(x, y);
|
|
386
|
+
if (isBall) {
|
|
387
|
+
line += "\x1B[97m\u25CF\x1B[0m";
|
|
388
|
+
} else if (isPaddle) {
|
|
389
|
+
line += "\x1B[94m\u2584\x1B[0m";
|
|
390
|
+
} else if (brickRow !== void 0) {
|
|
391
|
+
line += `\x1B[38;5;${BRICK_COLORS[brickRow]}m\u2580\x1B[0m`;
|
|
392
|
+
} else {
|
|
393
|
+
line += " ";
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
lines.push(line);
|
|
397
|
+
}
|
|
398
|
+
return lines.map((l) => `\u2502${l}\u2502`).join("\n");
|
|
399
|
+
}
|
|
400
|
+
function BrickBreakerGame({ onExit: _onExit }) {
|
|
401
|
+
const [initialLevel, setInitialLevel] = useState4(1);
|
|
402
|
+
const [selectingLevel, setSelectingLevel] = useState4(true);
|
|
403
|
+
const stateRef = useRef(createInitialState(initialLevel));
|
|
404
|
+
const [tick, setTick] = useState4(0);
|
|
405
|
+
const onExitRef = useRef(_onExit);
|
|
406
|
+
onExitRef.current = _onExit;
|
|
407
|
+
useEffect3(() => {
|
|
408
|
+
if (selectingLevel) return;
|
|
409
|
+
const interval = setInterval(() => {
|
|
410
|
+
update(stateRef.current);
|
|
411
|
+
setTick((t) => t + 1);
|
|
412
|
+
}, 80);
|
|
413
|
+
return () => clearInterval(interval);
|
|
414
|
+
}, [selectingLevel]);
|
|
415
|
+
const restart = useCallback3((level) => {
|
|
416
|
+
const lv = level ?? stateRef.current.level;
|
|
417
|
+
stateRef.current = createInitialState(lv);
|
|
418
|
+
setInitialLevel(lv);
|
|
419
|
+
setSelectingLevel(false);
|
|
420
|
+
setTick(0);
|
|
421
|
+
}, []);
|
|
422
|
+
const startLevelSelect = useCallback3(() => {
|
|
423
|
+
setSelectingLevel(true);
|
|
424
|
+
}, []);
|
|
425
|
+
useInput2(
|
|
426
|
+
useCallback3((input, key) => {
|
|
427
|
+
const s2 = stateRef.current;
|
|
428
|
+
if (selectingLevel) {
|
|
429
|
+
if (input >= "1" && input <= "9") {
|
|
430
|
+
restart(Number(input));
|
|
431
|
+
} else if (input === "0") {
|
|
432
|
+
restart(10);
|
|
433
|
+
} else if (key.escape || input === "q") {
|
|
434
|
+
onExitRef.current();
|
|
435
|
+
}
|
|
436
|
+
return;
|
|
437
|
+
}
|
|
438
|
+
if (key.leftArrow) {
|
|
439
|
+
s2.paddleX = Math.max(0, s2.paddleX - 1);
|
|
440
|
+
setTick((t) => t + 1);
|
|
441
|
+
} else if (key.rightArrow) {
|
|
442
|
+
s2.paddleX = Math.min(GAME_WIDTH - PADDLE_WIDTH, s2.paddleX + 1);
|
|
443
|
+
setTick((t) => t + 1);
|
|
444
|
+
} else if (input === "p" || input === " ") {
|
|
445
|
+
s2.paused = !s2.paused;
|
|
446
|
+
} else if (input === "r") {
|
|
447
|
+
if (s2.gameOver || s2.win) restart();
|
|
448
|
+
} else if (input === "l") {
|
|
449
|
+
if (s2.gameOver || s2.win) startLevelSelect();
|
|
450
|
+
} else if (input === "q" || key.escape) {
|
|
451
|
+
onExitRef.current();
|
|
452
|
+
}
|
|
453
|
+
}, [selectingLevel, restart, startLevelSelect])
|
|
454
|
+
);
|
|
455
|
+
const s = stateRef.current;
|
|
456
|
+
const aliveCount = s.bricks.filter((b) => b.alive).length;
|
|
457
|
+
const board = buildBoard(s);
|
|
458
|
+
const def = getLevel(s.level);
|
|
459
|
+
void tick;
|
|
460
|
+
return /* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
461
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "row", children: [
|
|
462
|
+
/* @__PURE__ */ jsx5(Box5, { width: 20, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
463
|
+
"\u5173\u5361 ",
|
|
464
|
+
s.level,
|
|
465
|
+
": ",
|
|
466
|
+
/* @__PURE__ */ jsx5(Text6, { color: "cyan", children: def.desc })
|
|
467
|
+
] }) }),
|
|
468
|
+
/* @__PURE__ */ jsx5(Box5, { width: 12, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
469
|
+
"\u5206\u6570: ",
|
|
470
|
+
/* @__PURE__ */ jsx5(Text6, { color: "yellow", children: String(s.score).padStart(3, "0") })
|
|
471
|
+
] }) }),
|
|
472
|
+
/* @__PURE__ */ jsx5(Box5, { width: 12, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
473
|
+
"\u751F\u547D: ",
|
|
474
|
+
/* @__PURE__ */ jsx5(Text6, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) })
|
|
475
|
+
] }) }),
|
|
476
|
+
/* @__PURE__ */ jsx5(Box5, { width: 10, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
477
|
+
"\u7816\u5757: ",
|
|
478
|
+
/* @__PURE__ */ jsx5(Text6, { color: "cyan", children: aliveCount })
|
|
479
|
+
] }) }),
|
|
480
|
+
/* @__PURE__ */ jsx5(Box5, { children: /* @__PURE__ */ jsxs5(Text6, { color: s.paused ? "gray" : "green", children: [
|
|
481
|
+
"[",
|
|
482
|
+
s.paused ? "\u6682\u505C" : "\u8FD0\u884C\u4E2D",
|
|
483
|
+
"]"
|
|
484
|
+
] }) })
|
|
485
|
+
] }),
|
|
486
|
+
/* @__PURE__ */ jsxs5(Box5, { flexDirection: "column", children: [
|
|
487
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
488
|
+
"\u250C",
|
|
489
|
+
"\u2500".repeat(GAME_WIDTH),
|
|
490
|
+
"\u2510"
|
|
491
|
+
] }),
|
|
492
|
+
/* @__PURE__ */ jsx5(Text6, { children: selectingLevel ? " \x1B[90m\u9009\u62E9\u5173\u5361\u540E\u5F00\u59CB...\x1B[0m" : board }),
|
|
493
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
494
|
+
"\u2514",
|
|
495
|
+
"\u2500".repeat(GAME_WIDTH),
|
|
496
|
+
"\u2518"
|
|
497
|
+
] })
|
|
498
|
+
] }),
|
|
499
|
+
selectingLevel && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, flexDirection: "column", children: [
|
|
500
|
+
/* @__PURE__ */ jsx5(Text6, { bold: true, color: "yellow", children: "\u9009\u62E9\u5173\u5361" }),
|
|
501
|
+
/* @__PURE__ */ jsx5(Box5, { flexDirection: "row", flexWrap: "wrap", children: LEVELS.map((lv, i) => /* @__PURE__ */ jsx5(Box5, { width: 22, children: /* @__PURE__ */ jsxs5(Text6, { children: [
|
|
502
|
+
/* @__PURE__ */ jsx5(Text6, { color: initialLevel === i + 1 ? "green" : "white", children: i + 1 === 10 ? "0" : String(i + 1) }),
|
|
503
|
+
". ",
|
|
504
|
+
lv.desc,
|
|
505
|
+
" (",
|
|
506
|
+
lv.rows,
|
|
507
|
+
"\xD7",
|
|
508
|
+
lv.cols,
|
|
509
|
+
")"
|
|
510
|
+
] }) }, i)) }),
|
|
511
|
+
/* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: /* @__PURE__ */ jsx5(Text6, { dimColor: true, children: "\u6309\u6570\u5B57\u9009\u5173 q \u9000\u51FA" }) })
|
|
512
|
+
] }),
|
|
513
|
+
!selectingLevel && (s.gameOver || s.win) && /* @__PURE__ */ jsxs5(Box5, { marginTop: 1, children: [
|
|
514
|
+
/* @__PURE__ */ jsx5(Text6, { bold: true, color: s.gameOver ? "red" : "green", children: s.gameOver ? "\u6E38\u620F\u7ED3\u675F\uFF01" : "\u606D\u559C\u901A\u5173\uFF01" }),
|
|
515
|
+
/* @__PURE__ */ jsxs5(Text6, { children: [
|
|
516
|
+
" \u5206\u6570: ",
|
|
517
|
+
/* @__PURE__ */ jsx5(Text6, { color: "yellow", children: s.score })
|
|
518
|
+
] })
|
|
519
|
+
] }),
|
|
520
|
+
!selectingLevel && /* @__PURE__ */ jsx5(Box5, { marginTop: 1, children: s.gameOver || s.win ? /* @__PURE__ */ jsx5(Text6, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 r \u91CD\u5F00 l \u9009\u5173 q \u9000\u51FA" }) : /* @__PURE__ */ jsx5(Text6, { dimColor: true, children: "\u2190 \u2192 \u79FB\u52A8 p \u6682\u505C q \u9000\u51FA" }) })
|
|
521
|
+
] });
|
|
522
|
+
}
|
|
523
|
+
var brick_breaker_default = {
|
|
524
|
+
id: "brick-breaker",
|
|
525
|
+
name: "Brick Breaker",
|
|
526
|
+
description: "\u7ECF\u5178\u6253\u7816\u5757\u6E38\u620F\uFF0C10 \u4E2A\u5173\u5361\u53EF\u9009\uFF01",
|
|
527
|
+
play: async () => {
|
|
528
|
+
await new Promise((resolve) => {
|
|
529
|
+
const { unmount } = render2(
|
|
530
|
+
/* @__PURE__ */ jsx5(BrickBreakerGame, { onExit: () => {
|
|
531
|
+
unmount();
|
|
532
|
+
resolve();
|
|
533
|
+
} })
|
|
534
|
+
);
|
|
535
|
+
});
|
|
536
|
+
}
|
|
537
|
+
};
|
|
538
|
+
|
|
539
|
+
// src/game/coder-check/index.tsx
|
|
540
|
+
import { Box as Box6, Text as Text7, useInput as useInput3, render as render3 } from "ink";
|
|
541
|
+
import { useState as useState5, useEffect as useEffect4, useRef as useRef2, useCallback as useCallback4 } from "react";
|
|
542
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
543
|
+
var GAME_W = 66;
|
|
544
|
+
var GAME_H = 20;
|
|
545
|
+
var SCORE_H = 6;
|
|
546
|
+
var MAX_WORDS = 10;
|
|
547
|
+
var CYBER_PALETTE2 = ["#00ffff", "#ff00ff", "#00ff41", "#ff1493", "#8b00ff"];
|
|
548
|
+
var DIGIT_ART = {
|
|
549
|
+
"0": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
550
|
+
"1": [" \u2588\u2588 ", " \u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
551
|
+
"2": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
552
|
+
"3": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
553
|
+
"4": ["\u2588\u2588 \u2588\u2588", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "],
|
|
554
|
+
"5": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
555
|
+
"6": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
556
|
+
"7": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588 "],
|
|
557
|
+
"8": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 "],
|
|
558
|
+
"9": [" \u2588\u2588\u2588\u2588\u2588\u2588 ", "\u2588\u2588 \u2588\u2588", " \u2588\u2588\u2588\u2588\u2588\u2588 ", " \u2588\u2588 ", " \u2588\u2588\u2588\u2588\u2588\u2588 "]
|
|
559
|
+
};
|
|
560
|
+
function buildScoreLines(scoreStr) {
|
|
561
|
+
const lines = ["", "", "", "", ""];
|
|
562
|
+
for (const ch of scoreStr) {
|
|
563
|
+
const art = DIGIT_ART[ch] ?? DIGIT_ART["0"];
|
|
564
|
+
for (let r = 0; r < 5; r++) {
|
|
565
|
+
lines[r] += " " + (art[r] ?? "");
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
const pad = 6;
|
|
569
|
+
return lines.map((l) => " ".repeat(pad) + l);
|
|
570
|
+
}
|
|
571
|
+
function hexToRgb(hex) {
|
|
572
|
+
const r = parseInt(hex.slice(1, 3), 16);
|
|
573
|
+
const g = parseInt(hex.slice(3, 5), 16);
|
|
574
|
+
const b = parseInt(hex.slice(5, 7), 16);
|
|
575
|
+
return `${r};${g};${b}`;
|
|
576
|
+
}
|
|
577
|
+
var WORDS_BANK = [
|
|
578
|
+
// ── 框架 & 库 ──
|
|
579
|
+
"react",
|
|
580
|
+
"vue",
|
|
581
|
+
"next",
|
|
582
|
+
"node",
|
|
583
|
+
"axios",
|
|
584
|
+
"express",
|
|
585
|
+
"lodash",
|
|
586
|
+
"jquery",
|
|
587
|
+
"webpack",
|
|
588
|
+
"vite",
|
|
589
|
+
"babel",
|
|
590
|
+
"eslint",
|
|
591
|
+
"prettier",
|
|
592
|
+
"tailwind",
|
|
593
|
+
"bootstrap",
|
|
594
|
+
"sass",
|
|
595
|
+
"less",
|
|
596
|
+
"postcss",
|
|
597
|
+
"redux",
|
|
598
|
+
"pinia",
|
|
599
|
+
"vuex",
|
|
600
|
+
"router",
|
|
601
|
+
"nestjs",
|
|
602
|
+
"socket",
|
|
603
|
+
"graphql",
|
|
604
|
+
"rest",
|
|
605
|
+
"grpc",
|
|
606
|
+
"prisma",
|
|
607
|
+
"typeorm",
|
|
608
|
+
// ── 前端 ──
|
|
609
|
+
"html",
|
|
610
|
+
"css",
|
|
611
|
+
"jsx",
|
|
612
|
+
"tsx",
|
|
613
|
+
"dom",
|
|
614
|
+
"spa",
|
|
615
|
+
"ssr",
|
|
616
|
+
"csr",
|
|
617
|
+
"pwa",
|
|
618
|
+
"component",
|
|
619
|
+
"prop",
|
|
620
|
+
"hook",
|
|
621
|
+
"composable",
|
|
622
|
+
"directive",
|
|
623
|
+
"filter",
|
|
624
|
+
"mixin",
|
|
625
|
+
"template",
|
|
626
|
+
"render",
|
|
627
|
+
"virtual",
|
|
628
|
+
"diff",
|
|
629
|
+
"patch",
|
|
630
|
+
"hydration",
|
|
631
|
+
"responsive",
|
|
632
|
+
"flexbox",
|
|
633
|
+
"grid",
|
|
634
|
+
"animation",
|
|
635
|
+
"transition",
|
|
636
|
+
// ── 后端 ──
|
|
637
|
+
"api",
|
|
638
|
+
"route",
|
|
639
|
+
"middleware",
|
|
640
|
+
"controller",
|
|
641
|
+
"service",
|
|
642
|
+
"module",
|
|
643
|
+
"dto",
|
|
644
|
+
"entity",
|
|
645
|
+
"schema",
|
|
646
|
+
"migration",
|
|
647
|
+
"seeder",
|
|
648
|
+
"factory",
|
|
649
|
+
"auth",
|
|
650
|
+
"jwt",
|
|
651
|
+
"oauth",
|
|
652
|
+
"session",
|
|
653
|
+
"cookie",
|
|
654
|
+
"token",
|
|
655
|
+
"cors",
|
|
656
|
+
"cache",
|
|
657
|
+
"redis",
|
|
658
|
+
"mq",
|
|
659
|
+
"rabbit",
|
|
660
|
+
"kafka",
|
|
661
|
+
"nats",
|
|
662
|
+
// ── 数据库 ──
|
|
663
|
+
"sql",
|
|
664
|
+
"mysql",
|
|
665
|
+
"pg",
|
|
666
|
+
"sqlite",
|
|
667
|
+
"mongo",
|
|
668
|
+
"redis",
|
|
669
|
+
"orm",
|
|
670
|
+
"table",
|
|
671
|
+
"index",
|
|
672
|
+
"query",
|
|
673
|
+
"join",
|
|
674
|
+
"union",
|
|
675
|
+
"group",
|
|
676
|
+
"order",
|
|
677
|
+
"where",
|
|
678
|
+
"having",
|
|
679
|
+
"limit",
|
|
680
|
+
"offset",
|
|
681
|
+
"insert",
|
|
682
|
+
"update",
|
|
683
|
+
"delete",
|
|
684
|
+
// ── DevOps ──
|
|
685
|
+
"docker",
|
|
686
|
+
"nginx",
|
|
687
|
+
"linux",
|
|
688
|
+
"bash",
|
|
689
|
+
"shell",
|
|
690
|
+
"yaml",
|
|
691
|
+
"toml",
|
|
692
|
+
"ci",
|
|
693
|
+
"cd",
|
|
694
|
+
"deploy",
|
|
695
|
+
"rollback",
|
|
696
|
+
"release",
|
|
697
|
+
"build",
|
|
698
|
+
"test",
|
|
699
|
+
"lint",
|
|
700
|
+
"format",
|
|
701
|
+
"stage",
|
|
702
|
+
"commit",
|
|
703
|
+
"branch",
|
|
704
|
+
"merge",
|
|
705
|
+
"rebase",
|
|
706
|
+
// ── 数据结构 & 算法 ──
|
|
707
|
+
"array",
|
|
708
|
+
"stack",
|
|
709
|
+
"queue",
|
|
710
|
+
"tree",
|
|
711
|
+
"graph",
|
|
712
|
+
"list",
|
|
713
|
+
"map",
|
|
714
|
+
"set",
|
|
715
|
+
"sort",
|
|
716
|
+
"search",
|
|
717
|
+
"filter",
|
|
718
|
+
"reduce",
|
|
719
|
+
"map",
|
|
720
|
+
"async",
|
|
721
|
+
"await",
|
|
722
|
+
"promise",
|
|
723
|
+
"callback",
|
|
724
|
+
"closure",
|
|
725
|
+
"proxy",
|
|
726
|
+
"reflect",
|
|
727
|
+
"decorator",
|
|
728
|
+
// ── 常用操作 ──
|
|
729
|
+
"create",
|
|
730
|
+
"read",
|
|
731
|
+
"update",
|
|
732
|
+
"delete",
|
|
733
|
+
"crud",
|
|
734
|
+
"parse",
|
|
735
|
+
"stringify",
|
|
736
|
+
"encode",
|
|
737
|
+
"decode",
|
|
738
|
+
"transform",
|
|
739
|
+
"validate",
|
|
740
|
+
"format",
|
|
741
|
+
"parse",
|
|
742
|
+
"upload",
|
|
743
|
+
"download",
|
|
744
|
+
"export",
|
|
745
|
+
"import",
|
|
746
|
+
"backup",
|
|
747
|
+
"restore",
|
|
748
|
+
// ── 类型 & 变量 ──
|
|
749
|
+
"string",
|
|
750
|
+
"number",
|
|
751
|
+
"boolean",
|
|
752
|
+
"object",
|
|
753
|
+
"array",
|
|
754
|
+
"tuple",
|
|
755
|
+
"enum",
|
|
756
|
+
"interface",
|
|
757
|
+
"type",
|
|
758
|
+
"class",
|
|
759
|
+
"function",
|
|
760
|
+
"method",
|
|
761
|
+
"property",
|
|
762
|
+
"public",
|
|
763
|
+
"private",
|
|
764
|
+
"static",
|
|
765
|
+
"readonly",
|
|
766
|
+
"optional",
|
|
767
|
+
"abstract",
|
|
768
|
+
"const",
|
|
769
|
+
"let",
|
|
770
|
+
"var",
|
|
771
|
+
"void",
|
|
772
|
+
"null",
|
|
773
|
+
"undef",
|
|
774
|
+
"never",
|
|
775
|
+
"any",
|
|
776
|
+
// ── 补充 ──
|
|
777
|
+
"config",
|
|
778
|
+
"logger",
|
|
779
|
+
"monitor",
|
|
780
|
+
"metric",
|
|
781
|
+
"alert",
|
|
782
|
+
"webhook",
|
|
783
|
+
"endpoint",
|
|
784
|
+
"payload",
|
|
785
|
+
"header",
|
|
786
|
+
"status",
|
|
787
|
+
"timeout",
|
|
788
|
+
"retry",
|
|
789
|
+
"fallback",
|
|
790
|
+
"circuit",
|
|
791
|
+
"breaker",
|
|
792
|
+
"throttle",
|
|
793
|
+
"debounce",
|
|
794
|
+
"scroll",
|
|
795
|
+
"resize",
|
|
796
|
+
"click",
|
|
797
|
+
"hover",
|
|
798
|
+
"focus",
|
|
799
|
+
"blur"
|
|
800
|
+
];
|
|
801
|
+
function randomWord(used) {
|
|
802
|
+
let w;
|
|
803
|
+
do {
|
|
804
|
+
w = WORDS_BANK[Math.floor(Math.random() * WORDS_BANK.length)];
|
|
805
|
+
} while (used.has(w));
|
|
806
|
+
return w;
|
|
807
|
+
}
|
|
808
|
+
function createInitialState2() {
|
|
809
|
+
return {
|
|
810
|
+
words: [],
|
|
811
|
+
score: 0,
|
|
812
|
+
lives: 3,
|
|
813
|
+
speed: 0.3,
|
|
814
|
+
spawnTimer: 0,
|
|
815
|
+
gameOver: false,
|
|
816
|
+
paused: false,
|
|
817
|
+
typed: "",
|
|
818
|
+
target: null,
|
|
819
|
+
combo: 0,
|
|
820
|
+
message: "",
|
|
821
|
+
messageTimer: 0,
|
|
822
|
+
usedWords: /* @__PURE__ */ new Set()
|
|
823
|
+
};
|
|
824
|
+
}
|
|
825
|
+
function pickTarget(s) {
|
|
826
|
+
let best = null;
|
|
827
|
+
for (const w of s.words) {
|
|
828
|
+
if (!best || w.col < best.col) best = w;
|
|
829
|
+
}
|
|
830
|
+
return best?.text ?? null;
|
|
831
|
+
}
|
|
832
|
+
function update2(s) {
|
|
833
|
+
if (s.paused || s.gameOver) return;
|
|
834
|
+
s.spawnTimer++;
|
|
835
|
+
if (s.spawnTimer >= Math.max(20, 50 - Math.floor(s.speed * 15))) {
|
|
836
|
+
s.spawnTimer = 0;
|
|
837
|
+
if (s.words.length < MAX_WORDS) {
|
|
838
|
+
const used = new Set(s.usedWords);
|
|
839
|
+
for (const w of s.words) used.add(w.text);
|
|
840
|
+
const text = randomWord(used);
|
|
841
|
+
const usedRows = new Set(s.words.map((w) => w.row));
|
|
842
|
+
let row = -1;
|
|
843
|
+
for (let r = SCORE_H; r < GAME_H; r++) {
|
|
844
|
+
if (!usedRows.has(r)) {
|
|
845
|
+
row = r;
|
|
846
|
+
break;
|
|
847
|
+
}
|
|
848
|
+
}
|
|
849
|
+
if (row >= 0) {
|
|
850
|
+
s.words.push({ text, row, col: GAME_W - 1 });
|
|
851
|
+
s.usedWords.add(text);
|
|
852
|
+
}
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
for (const w of s.words) {
|
|
856
|
+
w.col -= s.speed;
|
|
857
|
+
}
|
|
858
|
+
const before = s.words.length;
|
|
859
|
+
s.words = s.words.filter((w) => w.col > -w.text.length);
|
|
860
|
+
const removed = before - s.words.length;
|
|
861
|
+
if (removed > 0) {
|
|
862
|
+
s.lives -= removed;
|
|
863
|
+
s.typed = "";
|
|
864
|
+
s.target = pickTarget(s);
|
|
865
|
+
if (s.lives <= 0) {
|
|
866
|
+
s.gameOver = true;
|
|
867
|
+
s.words = [];
|
|
868
|
+
}
|
|
869
|
+
}
|
|
870
|
+
s.target = pickTarget(s);
|
|
871
|
+
if (s.messageTimer > 0) {
|
|
872
|
+
s.messageTimer--;
|
|
873
|
+
if (s.messageTimer <= 0) s.message = "";
|
|
874
|
+
}
|
|
875
|
+
}
|
|
876
|
+
function buildGameView(s, scoreLines, scoreColor, message) {
|
|
877
|
+
const rows = [];
|
|
878
|
+
for (let y = 0; y < GAME_H; y++) {
|
|
879
|
+
let line = "";
|
|
880
|
+
if (y < SCORE_H) {
|
|
881
|
+
if (y < 5) {
|
|
882
|
+
const raw = (scoreLines[y] ?? "").padEnd(GAME_W);
|
|
883
|
+
line = `\x1B[38;2;${hexToRgb(scoreColor)}m${raw}\x1B[0m`;
|
|
884
|
+
} else if (y === 5) {
|
|
885
|
+
if (s.combo >= 3) {
|
|
886
|
+
const comboText = `${s.combo}\u8FDE\u51FB!`;
|
|
887
|
+
const pad = Math.floor((GAME_W - comboText.length) / 2);
|
|
888
|
+
const comboColor = CYBER_PALETTE2[s.combo % CYBER_PALETTE2.length];
|
|
889
|
+
const raw = " ".repeat(pad) + comboText + " ".repeat(GAME_W - pad - comboText.length);
|
|
890
|
+
line = `\x1B[38;2;${hexToRgb(comboColor)}m${raw}\x1B[0m`;
|
|
891
|
+
} else if (s.paused) {
|
|
892
|
+
const pauseText = "\u6682\u505C";
|
|
893
|
+
const pad = Math.floor((GAME_W - pauseText.length) / 2);
|
|
894
|
+
line = " ".repeat(pad) + pauseText;
|
|
895
|
+
line = line.padEnd(GAME_W);
|
|
896
|
+
}
|
|
897
|
+
}
|
|
898
|
+
line = line.padEnd(GAME_W);
|
|
899
|
+
} else {
|
|
900
|
+
if (y === SCORE_H && message) {
|
|
901
|
+
const pad = Math.floor((GAME_W - message.length) / 2);
|
|
902
|
+
const raw = " ".repeat(pad) + message + " ".repeat(GAME_W - pad - message.length);
|
|
903
|
+
const msgColor = CYBER_PALETTE2[Math.floor(Math.random() * CYBER_PALETTE2.length)];
|
|
904
|
+
line = `\x1B[38;2;${hexToRgb(msgColor)}m${raw}\x1B[0m`;
|
|
905
|
+
} else {
|
|
906
|
+
for (let x = 0; x < GAME_W; x++) {
|
|
907
|
+
const word = s.words.find((w) => {
|
|
908
|
+
const charIdx = x - Math.floor(w.col);
|
|
909
|
+
return charIdx >= 0 && charIdx < w.text.length && w.row === y;
|
|
910
|
+
});
|
|
911
|
+
if (word) {
|
|
912
|
+
const charIdx = x - Math.floor(word.col);
|
|
913
|
+
const ch = word.text[charIdx];
|
|
914
|
+
const isTarget = word.text === s.target;
|
|
915
|
+
const typedIdx = s.target === word.text ? s.typed.length : 0;
|
|
916
|
+
const isTyped = isTarget && charIdx < typedIdx;
|
|
917
|
+
if (isTarget) {
|
|
918
|
+
line += isTyped ? `\x1B[92m${ch}\x1B[0m` : `\x1B[97m${ch}\x1B[0m`;
|
|
919
|
+
} else {
|
|
920
|
+
line += `\x1B[90m${ch}\x1B[0m`;
|
|
921
|
+
}
|
|
922
|
+
} else {
|
|
923
|
+
line += " ";
|
|
924
|
+
}
|
|
925
|
+
}
|
|
926
|
+
}
|
|
927
|
+
}
|
|
928
|
+
rows.push(line);
|
|
929
|
+
}
|
|
930
|
+
return rows;
|
|
931
|
+
}
|
|
932
|
+
function CoderCheck({ onExit: _onExit }) {
|
|
933
|
+
const stateRef = useRef2(createInitialState2());
|
|
934
|
+
const [tick, setTick] = useState5(0);
|
|
935
|
+
const [colorOffset, setColorOffset] = useState5(0);
|
|
936
|
+
const onExitRef = useRef2(_onExit);
|
|
937
|
+
onExitRef.current = _onExit;
|
|
938
|
+
useEffect4(() => {
|
|
939
|
+
const timer = setInterval(() => {
|
|
940
|
+
setColorOffset((prev) => (prev + 1) % CYBER_PALETTE2.length);
|
|
941
|
+
}, 400);
|
|
942
|
+
return () => clearInterval(timer);
|
|
943
|
+
}, []);
|
|
944
|
+
useEffect4(() => {
|
|
945
|
+
const interval = setInterval(() => {
|
|
946
|
+
update2(stateRef.current);
|
|
947
|
+
setTick((t) => t + 1);
|
|
948
|
+
}, 60);
|
|
949
|
+
return () => clearInterval(interval);
|
|
950
|
+
}, []);
|
|
951
|
+
useInput3(
|
|
952
|
+
useCallback4((input, key) => {
|
|
953
|
+
const s2 = stateRef.current;
|
|
954
|
+
if (s2.gameOver) {
|
|
955
|
+
if (input === "r") {
|
|
956
|
+
stateRef.current = createInitialState2();
|
|
957
|
+
setTick(0);
|
|
958
|
+
} else if (input === "q" || key.escape) {
|
|
959
|
+
onExitRef.current();
|
|
960
|
+
}
|
|
961
|
+
return;
|
|
962
|
+
}
|
|
963
|
+
if (input === "p" && key.ctrl || input === " ") {
|
|
964
|
+
s2.paused = !s2.paused;
|
|
965
|
+
return;
|
|
966
|
+
}
|
|
967
|
+
if (input === "q" && key.ctrl || key.escape) {
|
|
968
|
+
onExitRef.current();
|
|
969
|
+
return;
|
|
970
|
+
}
|
|
971
|
+
if (s2.paused) return;
|
|
972
|
+
if (input.length === 1 && input >= "a" && input <= "z") {
|
|
973
|
+
if (!s2.target) {
|
|
974
|
+
s2.target = pickTarget(s2);
|
|
975
|
+
}
|
|
976
|
+
if (s2.target) {
|
|
977
|
+
const nextChar = s2.target[s2.typed.length];
|
|
978
|
+
if (nextChar === input) {
|
|
979
|
+
s2.typed += input;
|
|
980
|
+
if (s2.typed === s2.target) {
|
|
981
|
+
s2.words = s2.words.filter((w) => w.text !== s2.target);
|
|
982
|
+
s2.combo++;
|
|
983
|
+
const prevScore = s2.score;
|
|
984
|
+
const basePts = s2.target.length;
|
|
985
|
+
const comboBonus = s2.combo >= 3 ? s2.score : 0;
|
|
986
|
+
s2.score += basePts + comboBonus;
|
|
987
|
+
s2.speed = s2.speed + 0.02;
|
|
988
|
+
const prevMilestone = Math.floor(prevScore / 500);
|
|
989
|
+
const newMilestone = Math.floor(s2.score / 500);
|
|
990
|
+
if (newMilestone > prevMilestone) {
|
|
991
|
+
s2.speed += 0.15;
|
|
992
|
+
}
|
|
993
|
+
if (s2.score >= 1e5 && prevScore < 1e5) {
|
|
994
|
+
s2.message = "\u606D\u559C\u901A\u5173! \u96BE\u5EA6\u6700\u5927\u5316!";
|
|
995
|
+
s2.messageTimer = 100;
|
|
996
|
+
}
|
|
997
|
+
s2.typed = "";
|
|
998
|
+
s2.target = pickTarget(s2);
|
|
999
|
+
}
|
|
1000
|
+
} else {
|
|
1001
|
+
s2.combo = 0;
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
}
|
|
1005
|
+
}, [])
|
|
1006
|
+
);
|
|
1007
|
+
const s = stateRef.current;
|
|
1008
|
+
const scoreColor = CYBER_PALETTE2[colorOffset];
|
|
1009
|
+
const scoreStr = String(s.score).padStart(5, "0");
|
|
1010
|
+
const scoreLines = buildScoreLines(scoreStr);
|
|
1011
|
+
const view = buildGameView(s, scoreLines, scoreColor, s.message);
|
|
1012
|
+
void tick;
|
|
1013
|
+
return /* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", paddingX: 1, children: [
|
|
1014
|
+
/* @__PURE__ */ jsx6(Box6, { flexDirection: "row", children: /* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1015
|
+
"\u751F\u547D ",
|
|
1016
|
+
/* @__PURE__ */ jsx6(Text7, { color: "red", children: "\u2665".repeat(Math.max(0, s.lives)) }),
|
|
1017
|
+
" ",
|
|
1018
|
+
"\u901F\u5EA6 ",
|
|
1019
|
+
/* @__PURE__ */ jsxs6(Text7, { color: "cyan", children: [
|
|
1020
|
+
"Lv.",
|
|
1021
|
+
Math.floor(s.speed * 10)
|
|
1022
|
+
] })
|
|
1023
|
+
] }) }),
|
|
1024
|
+
!s.gameOver && s.target && /* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1025
|
+
"\u6253\u5B57: ",
|
|
1026
|
+
/* @__PURE__ */ jsx6(Text7, { color: "green", children: s.typed }),
|
|
1027
|
+
/* @__PURE__ */ jsx6(Text7, { color: "white", children: s.target.slice(s.typed.length) })
|
|
1028
|
+
] }) }),
|
|
1029
|
+
/* @__PURE__ */ jsxs6(Box6, { flexDirection: "column", marginTop: 1, children: [
|
|
1030
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1031
|
+
"\u250C",
|
|
1032
|
+
"\u2500".repeat(GAME_W),
|
|
1033
|
+
"\u2510"
|
|
1034
|
+
] }),
|
|
1035
|
+
view.map((row, i) => /* @__PURE__ */ jsx6(Text7, { children: `\u2502${row}\u2502` }, i)),
|
|
1036
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1037
|
+
"\u2514",
|
|
1038
|
+
"\u2500".repeat(GAME_W),
|
|
1039
|
+
"\u2518"
|
|
1040
|
+
] })
|
|
1041
|
+
] }),
|
|
1042
|
+
s.gameOver && /* @__PURE__ */ jsxs6(Box6, { marginTop: 1, children: [
|
|
1043
|
+
/* @__PURE__ */ jsx6(Text7, { bold: true, color: "red", children: "\u6E38\u620F\u7ED3\u675F\uFF01" }),
|
|
1044
|
+
/* @__PURE__ */ jsxs6(Text7, { children: [
|
|
1045
|
+
" \u5F97\u5206: ",
|
|
1046
|
+
/* @__PURE__ */ jsx6(Text7, { color: "yellow", children: s.score }),
|
|
1047
|
+
" r \u91CD\u5F00 q \u9000\u51FA"
|
|
1048
|
+
] })
|
|
1049
|
+
] }),
|
|
1050
|
+
/* @__PURE__ */ jsx6(Box6, { marginTop: 1, children: /* @__PURE__ */ jsx6(Text7, { dimColor: true, children: "\u6253\u5B57\u6D88\u9664\u5355\u8BCD \u7A7A\u683C/Ctrl+P\u6682\u505C Ctrl+Q\u9000\u51FA" }) })
|
|
1051
|
+
] });
|
|
1052
|
+
}
|
|
1053
|
+
var coder_check_default = {
|
|
1054
|
+
id: "coder-check",
|
|
1055
|
+
name: "Coder Check",
|
|
1056
|
+
description: "\u6781\u901F\u6253\u5B57\u6E38\u620F\uFF0C\u8F93\u5165\u5355\u8BCD\u6D88\u9664\u5B83\u4EEC\uFF01",
|
|
1057
|
+
play: async () => {
|
|
1058
|
+
await new Promise((resolve) => {
|
|
1059
|
+
const { unmount } = render3(
|
|
1060
|
+
/* @__PURE__ */ jsx6(CoderCheck, { onExit: () => {
|
|
1061
|
+
unmount();
|
|
1062
|
+
resolve();
|
|
1063
|
+
} })
|
|
1064
|
+
);
|
|
1065
|
+
});
|
|
1066
|
+
}
|
|
1067
|
+
};
|
|
1068
|
+
|
|
1069
|
+
// src/game/registry.ts
|
|
1070
|
+
function initGames() {
|
|
1071
|
+
registerGame(brick_breaker_default);
|
|
1072
|
+
registerGame(coder_check_default);
|
|
1073
|
+
return listGames();
|
|
1074
|
+
}
|
|
1075
|
+
|
|
217
1076
|
// src/cli/index.tsx
|
|
218
|
-
import {
|
|
219
|
-
|
|
1077
|
+
import { render as render4 } from "ink";
|
|
1078
|
+
import chalk2 from "chalk";
|
|
1079
|
+
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1080
|
+
var SUBCOMMANDS = ["chat", "run", "setup", "init", "completion", "game"];
|
|
220
1081
|
function createCli() {
|
|
221
1082
|
const program2 = new Command();
|
|
222
1083
|
program2.exitOverride();
|
|
@@ -233,7 +1094,7 @@ function createCli() {
|
|
|
233
1094
|
}
|
|
234
1095
|
const ctx = this.dskcodeCtx;
|
|
235
1096
|
const app = renderApp(
|
|
236
|
-
/* @__PURE__ */
|
|
1097
|
+
/* @__PURE__ */ jsx7(
|
|
237
1098
|
ChatSession,
|
|
238
1099
|
{
|
|
239
1100
|
providerCount: ctx?.config.providers.length ?? 1,
|
|
@@ -279,12 +1140,56 @@ _dskcode_completion() {
|
|
|
279
1140
|
"setup:\u8FD0\u884C\u914D\u7F6E\u5411\u5BFC"
|
|
280
1141
|
"init:\u751F\u6210\u9879\u76EE\u8BB0\u5FC6\u6587\u4EF6"
|
|
281
1142
|
"completion:\u8F93\u51FA shell \u81EA\u52A8\u8865\u5168\u8BF4\u660E"
|
|
1143
|
+
"game:\u5185\u7F6E\u5C0F\u6E38\u620F"
|
|
282
1144
|
)
|
|
283
1145
|
_describe 'dskcode commands' commands
|
|
284
1146
|
}
|
|
285
1147
|
compdef _dskcode_completion dskcode`);
|
|
286
1148
|
}
|
|
287
1149
|
});
|
|
1150
|
+
initGames();
|
|
1151
|
+
program2.command("game").description("\u542F\u52A8\u5185\u7F6E\u5C0F\u6E38\u620F").argument("[name]", "\u6E38\u620F\u540D\u79F0\uFF0C\u4E0D\u6307\u5B9A\u5219\u663E\u793A\u4EA4\u4E92\u5F0F\u6E38\u620F\u5217\u8868").action(async function(name) {
|
|
1152
|
+
if (name) {
|
|
1153
|
+
const game = getGame(name);
|
|
1154
|
+
if (!game) {
|
|
1155
|
+
console.error(`\u672A\u627E\u5230\u6E38\u620F "${name}"\u3002\u4F7F\u7528 dskcode game \u67E5\u770B\u53EF\u7528\u6E38\u620F\u5217\u8868\u3002`);
|
|
1156
|
+
process.exit(1);
|
|
1157
|
+
}
|
|
1158
|
+
console.log(`\u6B63\u5728\u542F\u52A8: ${game.name} \u2014 ${game.description}
|
|
1159
|
+
`);
|
|
1160
|
+
await game.play();
|
|
1161
|
+
} else {
|
|
1162
|
+
const games = listGames();
|
|
1163
|
+
if (games.length === 0) {
|
|
1164
|
+
console.log("\u6682\u65E0\u53EF\u7528\u6E38\u620F\u3002");
|
|
1165
|
+
return;
|
|
1166
|
+
}
|
|
1167
|
+
const selectedGame = await new Promise((resolve) => {
|
|
1168
|
+
const { unmount } = render4(
|
|
1169
|
+
/* @__PURE__ */ jsx7(
|
|
1170
|
+
GamePicker,
|
|
1171
|
+
{
|
|
1172
|
+
games,
|
|
1173
|
+
onSelect: (game) => {
|
|
1174
|
+
unmount();
|
|
1175
|
+
resolve(game);
|
|
1176
|
+
},
|
|
1177
|
+
onExit: () => {
|
|
1178
|
+
unmount();
|
|
1179
|
+
resolve(null);
|
|
1180
|
+
}
|
|
1181
|
+
}
|
|
1182
|
+
)
|
|
1183
|
+
);
|
|
1184
|
+
});
|
|
1185
|
+
if (selectedGame) {
|
|
1186
|
+
console.log(`
|
|
1187
|
+
\u542F\u52A8\u6E38\u620F: ${chalk2.green(selectedGame.name)}
|
|
1188
|
+
`);
|
|
1189
|
+
await selectedGame.play();
|
|
1190
|
+
}
|
|
1191
|
+
}
|
|
1192
|
+
});
|
|
288
1193
|
return program2;
|
|
289
1194
|
}
|
|
290
1195
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli/index.tsx","../src/cli/middleware.ts","../src/cli/help.ts","../src/ui/RenderScope.tsx","../src/ui/Spinner.tsx","../src/ui/StatusMessage.tsx","../src/ui/DskcodeSplash.tsx","../src/ui/ChatSession.tsx","../src/cli/exit-codes.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { loadConfigMiddleware } from \"./middleware.js\";\r\nimport { customHelp } from \"./help.js\";\r\nimport { renderApp, ChatSession } from \"../ui/index.js\";\r\n\r\nconst SUBCOMMANDS = [\"chat\", \"run\", \"setup\", \"init\", \"completion\"];\r\n\r\nexport function createCli(): Command {\r\n const program = new Command();\r\n program.exitOverride();\r\n\r\n program\r\n .name(\"dskcode\")\r\n .description(\"基于 DeepSeek 的 AI 编程助手终端工具\")\r\n .version(\"0.0.0\", \"-V, --version\", \"显示版本号\")\r\n .option(\"--verbose\", \"开启详细日志输出\")\r\n .option(\"--config <path>\", \"指定配置文件路径\");\r\n\r\n program.helpInformation = () => customHelp(program);\r\n\r\n program.hook(\"preAction\", async (thisCommand) => {\r\n const ctx = await loadConfigMiddleware.call(thisCommand);\r\n (thisCommand as unknown as Record<string, unknown>).dskcodeCtx = ctx;\r\n });\r\n\r\n // chat — 交互式对话\r\n program\r\n .command(\"chat\")\r\n .description(\"启动交互式对话会话\")\r\n .action(async function () {\r\n if (!process.stdin.isTTY) {\r\n console.error(\"dskcode chat 需要交互式终端。如需执行一次性任务,请使用 dskcode run。\");\r\n process.exit(1);\r\n }\r\n\r\n const ctx = (this as unknown as Record<string, unknown>).dskcodeCtx as\r\n | { verbose: boolean; config: { providers: unknown[]; tools: unknown[] } }\r\n | undefined;\r\n\r\n const app = renderApp(\r\n <ChatSession\r\n providerCount={ctx?.config.providers.length ?? 1}\r\n toolCount={ctx?.config.tools.length ?? 0}\r\n verbose={ctx?.verbose ?? false}\r\n />,\r\n );\r\n\r\n await app.waitUntilExit;\r\n });\r\n\r\n // run\r\n program\r\n .command(\"run\")\r\n .description(\"执行一次性任务\")\r\n .argument(\"[prompt...]\", \"任务描述\")\r\n .option(\"--model <name>\", \"指定使用的模型\")\r\n .action(async function (_prompt: string[]) {\r\n console.log(\"dskcode run — 待实现(第07章)\");\r\n });\r\n\r\n // setup\r\n program\r\n .command(\"setup\")\r\n .description(\"运行配置向导\")\r\n .option(\"--export\", \"以 JSON 格式导出配置\")\r\n .option(\"--test\", \"测试 API Key 连通性\")\r\n .action(async function () {\r\n console.log(\"dskcode setup — 待实现(第14章)\");\r\n });\r\n\r\n // init\r\n program\r\n .command(\"init\")\r\n .description(\"在当前项目下生成项目记忆文件(AGENTS.md)\")\r\n .action(async function () {\r\n console.log(\"dskcode init — 待实现(第11章)\");\r\n });\r\n\r\n // completion\r\n program\r\n .command(\"completion\")\r\n .description(\"输出 shell 自动补全配置说明(bash/zsh)\")\r\n .argument(\"[shell]\", \"shell 类型\", /^(bash|zsh)$/i)\r\n .action(async function (shell?: string) {\r\n if (!shell) {\r\n console.log(\"请指定 shell 类型:dskcode completion bash 或 dskcode completion zsh\");\r\n return;\r\n }\r\n if (shell === \"bash\") {\r\n console.log(`# dskcode bash 自动补全\r\n_dskcode_completion() {\r\n local cur=\\${COMP_WORDS[COMP_CWORD]}\r\n if [[ \\${COMP_CWORD} -eq 1 ]]; then\r\n COMPREPLY=( $(compgen -W \"${SUBCOMMANDS.join(\" \")}\" -- \"\\${cur}\") )\r\n return 0\r\n fi\r\n COMPREPLY=( $(compgen -W \"--verbose --config --model\" -- \"\\${cur}\") )\r\n}\r\ncomplete -F _dskcode_completion dskcode`);\r\n } else {\r\n console.log(`# dskcode zsh 自动补全\r\n_dskcode_completion() {\r\n local -a commands\r\n commands=(\r\n \"chat:启动交互式对话会话\"\r\n \"run:执行一次性任务\"\r\n \"setup:运行配置向导\"\r\n \"init:生成项目记忆文件\"\r\n \"completion:输出 shell 自动补全说明\"\r\n )\r\n _describe 'dskcode commands' commands\r\n}\r\ncompdef _dskcode_completion dskcode`);\r\n }\r\n });\r\n\r\n return program;\r\n}\r\n","import type { Command } from \"commander\";\r\nimport type { Config } from \"../config/index.js\";\r\nimport { loadConfig } from \"../config/index.js\";\r\n\r\n/**\r\n * dskcode 运行时上下文。\r\n * 通过 commander 的 preAction hook 注入到每个命令中。\r\n */\r\nexport interface DskcodeContext {\r\n config: Config;\r\n verbose: boolean;\r\n}\r\n\r\n/**\r\n * 在 preAction hook 中加载配置并构造上下文。\r\n */\r\nexport async function loadConfigMiddleware(this: Command): Promise<DskcodeContext> {\r\n const opts = this.optsWithGlobals() as { verbose?: boolean; config?: string };\r\n const verbose = opts.verbose ?? false;\r\n\r\n let config: Config;\r\n try {\r\n config = await loadConfig(opts.config);\r\n } catch {\r\n const { defaultConfig } = await import(\"../config/index.js\");\r\n config = defaultConfig;\r\n }\r\n\r\n return { config, verbose };\r\n}\r\n","import type { Command } from \"commander\";\r\nimport chalk from \"chalk\";\r\n\r\nexport function customHelp(program: Command): string {\r\n const lines: string[] = [];\r\n\r\n lines.push(\"\");\r\n lines.push(chalk.bold(\"用法:\"));\r\n lines.push(` ${chalk.cyan(\"dskcode\")} ${chalk.dim(\"[global-options]\")} ${chalk.green(\"<command>\")} ${chalk.dim(\"[options]\")}`);\r\n lines.push(\"\");\r\n\r\n const globalOpts = program.options.filter(\r\n (o) => o.long !== \"--help\" && o.long !== \"--version\" && o.long !== \"--config\",\r\n );\r\n if (globalOpts.length > 0) {\r\n lines.push(chalk.bold(\"全局选项:\"));\r\n for (const opt of globalOpts) {\r\n const flags = [opt.short, opt.long].filter(Boolean).join(\", \");\r\n lines.push(` ${chalk.cyan(flags.padEnd(24))} ${opt.description ?? \"\"}`);\r\n }\r\n lines.push(\"\");\r\n }\r\n\r\n lines.push(chalk.bold(\"内置选项:\"));\r\n for (const flag of [\"-h, --help\", \"-V, --version\"]) {\r\n const opt = program.options.find(\r\n (o) => o.long === (flag.includes(\"help\") ? \"--help\" : \"--version\"),\r\n );\r\n if (opt) {\r\n lines.push(` ${chalk.cyan(flag.padEnd(24))} ${opt.description ?? \"\"}`);\r\n }\r\n }\r\n lines.push(\"\");\r\n\r\n const cmds = program.commands.filter((c) => !c.name().startsWith(\"help\"));\r\n if (cmds.length > 0) {\r\n lines.push(chalk.bold(\"命令:\"));\r\n for (const cmd of cmds) {\r\n lines.push(` ${chalk.green(cmd.name().padEnd(24))} ${cmd.description()}`);\r\n }\r\n lines.push(\"\");\r\n }\r\n\r\n lines.push(chalk.bold(\"示例:\"));\r\n lines.push(` ${chalk.dim(\"# 启动交互式对话\")}`);\r\n lines.push(\" dskcode chat\");\r\n lines.push(` ${chalk.dim(\"# 让 AI 执行一个任务\")}`);\r\n lines.push(\" dskcode run 修改所有 TODO 注释\");\r\n lines.push(` ${chalk.dim(\"# 运行配置向导\")}`);\r\n lines.push(\" dskcode setup\");\r\n lines.push(` ${chalk.dim(\"# 生成 shell 自动补全\")}`);\r\n lines.push(\" dskcode completion\");\r\n lines.push(\"\");\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","import { render } from \"ink\";\r\nimport type { ReactNode } from \"react\";\r\n\r\nexport interface RenderScopeHandle {\r\n waitUntilExit: Promise<unknown>;\r\n unmount: () => void;\r\n clear: () => void;\r\n}\r\n\r\nexport function renderApp(node: ReactNode): RenderScopeHandle {\r\n const { waitUntilExit, clear, unmount } = render(node);\r\n return { waitUntilExit: waitUntilExit(), clear, unmount };\r\n}\r\n\r\nexport async function unmountApp(handle: RenderScopeHandle): Promise<void> {\r\n handle.unmount();\r\n await new Promise((resolve) => setTimeout(resolve, 50));\r\n}\r\n","import { Text } from \"ink\";\r\nimport InkSpinner from \"ink-spinner\";\r\n\r\ninterface SpinnerProps {\r\n type?: \"dots\" | \"line\" | \"bouncingBar\" | \"aesthetic\";\r\n label?: string;\r\n}\r\n\r\nexport function Spinner({ type = \"dots\", label }: SpinnerProps) {\r\n return (\r\n <Text>\r\n <Text color=\"cyan\">\r\n <InkSpinner type={type} />\r\n </Text>\r\n {label ? <Text> {label}</Text> : null}\r\n </Text>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\n\r\ntype MessageType = \"info\" | \"success\" | \"warning\" | \"error\";\r\n\r\ninterface StatusMessageProps {\r\n type?: MessageType;\r\n label: string;\r\n detail?: string;\r\n}\r\n\r\nconst STYLES: Record<MessageType, { color: string; icon: string }> = {\r\n info: { color: \"cyan\", icon: \"ℹ\" },\r\n success: { color: \"green\", icon: \"✔\" },\r\n warning: { color: \"yellow\", icon: \"⚠\" },\r\n error: { color: \"red\", icon: \"✖\" },\r\n};\r\n\r\nexport function StatusMessage({ type = \"info\", label, detail }: StatusMessageProps) {\r\n const { color, icon } = STYLES[type];\r\n return (\r\n <Box>\r\n <Text color={color}>\r\n {icon} {label}\r\n </Text>\r\n {detail ? <Text dimColor>: {detail}</Text> : null}\r\n </Box>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nconst CYBER_PALETTE = [\"#00ffff\", \"#ff00ff\", \"#00ff41\", \"#ff1493\", \"#8b00ff\"];\r\n\r\nconst LOGO_LINES = [\r\n \" ██████╗ ███████╗██╗ ██╗\",\r\n \" ██╔══██╗██╔════╝██║ ██╔╝\",\r\n \" ██║ ██║███████╗█████╔╝ \",\r\n \" ██║ ██║╚════██║██╔═██╗ \",\r\n \" ██████╔╝███████║██║ ██╗\",\r\n \" ╚═════╝ ╚══════╝╚═╝ ╚═╝\",\r\n];\r\n\r\nexport function DskcodeSplash() {\r\n const [offset, setOffset] = useState(0);\r\n\r\n useEffect(() => {\r\n const timer = setInterval(() => {\r\n setOffset((prev) => (prev + 1) % CYBER_PALETTE.length);\r\n }, 500);\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n return (\r\n <Box flexDirection=\"column\" paddingLeft={1}>\r\n {LOGO_LINES.map((line, i) => {\r\n const colorIndex = (i + offset) % CYBER_PALETTE.length;\r\n return (\r\n <Box key={i}>\r\n <Text bold color={CYBER_PALETTE[colorIndex]}>\r\n {line}\r\n </Text>\r\n </Box>\r\n );\r\n })}\r\n </Box>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\nimport TextInput from \"ink-text-input\";\r\nimport { useEffect, useState, useCallback } from \"react\";\r\n\r\nconst CYBER_PALETTE = [\"#00ffff\", \"#ff00ff\", \"#00ff41\", \"#ff1493\", \"#8b00ff\"];\r\n\r\nconst LOGO_LINES = [\r\n \" ██████╗ ███████╗██╗ ██╗\",\r\n \" ██╔══██╗██╔════╝██║ ██╔╝\",\r\n \" ██║ ██║███████╗█████╔╝ \",\r\n \" ██║ ██║╚════██║██╔═██╗ \",\r\n \" ██████╔╝███████║██║ ██╗\",\r\n \" ╚═════╝ ╚══════╝╚═╝ ╚═╝\",\r\n];\r\n\r\nconst COMMANDS: Record<string, { desc: string; handler: () => string }> = {\r\n \"/exit\": { desc: \"退出对话\", handler: () => \"\" },\r\n \"/quit\": { desc: \"退出对话\", handler: () => \"\" },\r\n \"/help\": {\r\n desc: \"显示帮助信息\",\r\n handler: () =>\r\n [\r\n \"可用命令:\",\r\n \" /exit, /quit 退出对话\",\r\n \" /help 显示此帮助\",\r\n \" /clear 清空对话历史\",\r\n \" /version 显示版本信息\",\r\n ].join(\"\\n\"),\r\n },\r\n \"/clear\": { desc: \"清空对话历史\", handler: () => \"\" },\r\n \"/version\": { desc: \"显示版本信息\", handler: () => \"dskcode v0.0.0\" },\r\n};\r\n\r\ninterface ChatMessage {\r\n role: \"user\" | \"assistant\";\r\n content: string;\r\n}\r\n\r\ninterface ChatSessionProps {\r\n providerCount: number;\r\n toolCount: number;\r\n verbose: boolean;\r\n}\r\n\r\nexport function ChatSession({ providerCount, toolCount, verbose }: ChatSessionProps) {\r\n const [offset, setOffset] = useState(0);\r\n const [messages, setMessages] = useState<ChatMessage[]>([]);\r\n const [input, setInput] = useState(\"\");\r\n\r\n useEffect(() => {\r\n const timer = setInterval(() => {\r\n setOffset((prev) => (prev + 1) % CYBER_PALETTE.length);\r\n }, 500);\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n const handleSubmit = useCallback((value: string) => {\r\n const trimmed = value.trim();\r\n if (!trimmed) return;\r\n\r\n if (trimmed.startsWith(\"/\")) {\r\n const cmd = COMMANDS[trimmed.toLowerCase()];\r\n if (cmd) {\r\n if (trimmed.toLowerCase() === \"/exit\" || trimmed.toLowerCase() === \"/quit\") {\r\n process.exit(0);\r\n return;\r\n }\r\n if (trimmed.toLowerCase() === \"/clear\") {\r\n setMessages([]);\r\n setInput(\"\");\r\n return;\r\n }\r\n const result = cmd.handler();\r\n if (result) {\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: result },\r\n ]);\r\n }\r\n setInput(\"\");\r\n return;\r\n }\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: `未知命令:${trimmed}。输入 /help 查看。` },\r\n ]);\r\n setInput(\"\");\r\n return;\r\n }\r\n\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: \"dskcode AI — 待实现(第07章)。当前为 CLI 框架演示模式。\" },\r\n ]);\r\n setInput(\"\");\r\n }, []);\r\n\r\n return (\r\n <Box flexDirection=\"column\" paddingLeft={1} paddingRight={1}>\r\n {/* Logo + 状态栏 — 左右布局 */}\r\n <Box flexDirection=\"row\" marginBottom={1}>\r\n {/* Logo */}\r\n <Box flexDirection=\"column\" marginRight={4}>\r\n {LOGO_LINES.map((line, i) => {\r\n const colorIndex = (i + offset) % CYBER_PALETTE.length;\r\n return (\r\n <Box key={i}>\r\n <Text bold color={CYBER_PALETTE[colorIndex]}>\r\n {line}\r\n </Text>\r\n </Box>\r\n );\r\n })}\r\n </Box>\r\n\r\n {/* 状态信息 */}\r\n <Box flexDirection=\"column\" justifyContent=\"center\">\r\n <Text color=\"#00ff41\">{\" ✔ \"}已加载 {providerCount} 个 Provider</Text>\r\n <Text color=\"#00ffff\">{\" ℹ \"}已就绪 {toolCount} 个工具</Text>\r\n {verbose ? <Text color=\"#ff1493\">{\" ⚡ Verbose\"}</Text> : null}\r\n </Box>\r\n </Box>\r\n\r\n {/* Messages */}\r\n <Box flexDirection=\"column\" marginTop={1}>\r\n {messages.map((msg, i) => (\r\n <Box key={i} marginTop={1}>\r\n <Box width={8} flexShrink={0}>\r\n <Text bold color={msg.role === \"user\" ? \"#00ff41\" : \"#ff00ff\"}>\r\n {msg.role === \"user\" ? \" 👤\" : \" 🤖\"}\r\n </Text>\r\n </Box>\r\n <Box flexGrow={1}>\r\n <Text wrap=\"wrap\">{msg.content}</Text>\r\n </Box>\r\n </Box>\r\n ))}\r\n </Box>\r\n\r\n {/* Input */}\r\n <Box marginTop={1}>\r\n <Box width={8} flexShrink={0}>\r\n <Text bold color=\"#00ff41\">\r\n {\" ⚡\"}\r\n </Text>\r\n </Box>\r\n <Box flexGrow={1}>\r\n <TextInput\r\n value={input}\r\n onChange={setInput}\r\n onSubmit={handleSubmit}\r\n placeholder=\"输入你的问题...\"\r\n />\r\n </Box>\r\n </Box>\r\n\r\n <Box marginTop={1}>\r\n <Text color=\"#00ffff\" dimColor>\r\n {\" \" + \"─\".repeat(36)}\r\n </Text>\r\n </Box>\r\n </Box>\r\n );\r\n}\r\n","/** dskcode 退出码规范 */\r\nexport const ExitCode = {\r\n /** 正常执行完成 */\r\n SUCCESS: 0,\r\n /** 通用错误 */\r\n GENERAL_ERROR: 1,\r\n /** 配置错误 */\r\n CONFIG_ERROR: 2,\r\n /** 用户通过 Ctrl+C 中断 */\r\n SIGINT: 130,\r\n} as const;\r\n","#!/usr/bin/env node\r\n\r\nimport { createCli } from \"./cli/index.js\";\r\nimport { ExitCode } from \"./cli/exit-codes.js\";\r\n\r\nprocess.on(\"SIGINT\", () => {\r\n process.exit(ExitCode.SIGINT);\r\n});\r\n\r\nconst program = createCli();\r\n\r\ntry {\r\n await program.parseAsync(process.argv);\r\n} catch (err: unknown) {\r\n const error = err as { exitCode?: number; code?: string };\r\n\r\n if (error.code === \"commander.helpDisplayed\" || error.code === \"commander.version\") {\r\n process.exit(error.exitCode ?? ExitCode.SUCCESS);\r\n }\r\n\r\n if (typeof error.exitCode === \"number\") {\r\n process.exit(error.exitCode);\r\n }\r\n\r\n console.error(String(err));\r\n process.exit(ExitCode.GENERAL_ERROR);\r\n}\r\n"],"mappings":"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","names":["program","Text","jsxs","Box","Text","jsx","Box","Text","useEffect","useState","jsx","jsxs","jsx","program"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli/index.tsx","../src/cli/middleware.ts","../src/cli/help.ts","../src/ui/RenderScope.tsx","../src/ui/Spinner.tsx","../src/ui/StatusMessage.tsx","../src/ui/DskcodeSplash.tsx","../src/ui/ChatSession.tsx","../src/ui/GamePicker.tsx","../src/game/index.ts","../src/game/brick-breaker/index.tsx","../src/game/coder-check/index.tsx","../src/game/registry.ts","../src/cli/exit-codes.ts","../src/index.ts"],"sourcesContent":["import { Command } from \"commander\";\r\nimport { loadConfigMiddleware } from \"./middleware.js\";\r\nimport { customHelp } from \"./help.js\";\r\nimport { renderApp, ChatSession } from \"../ui/index.js\";\r\nimport { initGames } from \"../game/registry.js\";\r\nimport { listGames, getGame } from \"../game/index.js\";\r\nimport type { Game } from \"../game/index.js\";\r\nimport { GamePicker } from \"../ui/GamePicker.js\";\r\nimport { render } from \"ink\";\r\nimport chalk from \"chalk\";\r\n\r\nconst SUBCOMMANDS = [\"chat\", \"run\", \"setup\", \"init\", \"completion\", \"game\"];\r\n\r\nexport function createCli(): Command {\r\n const program = new Command();\r\n program.exitOverride();\r\n\r\n program\r\n .name(\"dskcode\")\r\n .description(\"基于 DeepSeek 的 AI 编程助手终端工具\")\r\n .version(\"0.0.0\", \"-V, --version\", \"显示版本号\")\r\n .option(\"--verbose\", \"开启详细日志输出\")\r\n .option(\"--config <path>\", \"指定配置文件路径\");\r\n\r\n program.helpInformation = () => customHelp(program);\r\n\r\n program.hook(\"preAction\", async (thisCommand) => {\r\n const ctx = await loadConfigMiddleware.call(thisCommand);\r\n (thisCommand as unknown as Record<string, unknown>).dskcodeCtx = ctx;\r\n });\r\n\r\n // chat — 交互式对话\r\n program\r\n .command(\"chat\")\r\n .description(\"启动交互式对话会话\")\r\n .action(async function () {\r\n if (!process.stdin.isTTY) {\r\n console.error(\"dskcode chat 需要交互式终端。如需执行一次性任务,请使用 dskcode run。\");\r\n process.exit(1);\r\n }\r\n\r\n const ctx = (this as unknown as Record<string, unknown>).dskcodeCtx as\r\n | { verbose: boolean; config: { providers: unknown[]; tools: unknown[] } }\r\n | undefined;\r\n\r\n const app = renderApp(\r\n <ChatSession\r\n providerCount={ctx?.config.providers.length ?? 1}\r\n toolCount={ctx?.config.tools.length ?? 0}\r\n verbose={ctx?.verbose ?? false}\r\n />,\r\n );\r\n\r\n await app.waitUntilExit;\r\n });\r\n\r\n // run\r\n program\r\n .command(\"run\")\r\n .description(\"执行一次性任务\")\r\n .argument(\"[prompt...]\", \"任务描述\")\r\n .option(\"--model <name>\", \"指定使用的模型\")\r\n .action(async function (_prompt: string[]) {\r\n console.log(\"dskcode run — 待实现(第07章)\");\r\n });\r\n\r\n // setup\r\n program\r\n .command(\"setup\")\r\n .description(\"运行配置向导\")\r\n .option(\"--export\", \"以 JSON 格式导出配置\")\r\n .option(\"--test\", \"测试 API Key 连通性\")\r\n .action(async function () {\r\n console.log(\"dskcode setup — 待实现(第14章)\");\r\n });\r\n\r\n // init\r\n program\r\n .command(\"init\")\r\n .description(\"在当前项目下生成项目记忆文件(AGENTS.md)\")\r\n .action(async function () {\r\n console.log(\"dskcode init — 待实现(第11章)\");\r\n });\r\n\r\n // completion\r\n program\r\n .command(\"completion\")\r\n .description(\"输出 shell 自动补全配置说明(bash/zsh)\")\r\n .argument(\"[shell]\", \"shell 类型\", /^(bash|zsh)$/i)\r\n .action(async function (shell?: string) {\r\n if (!shell) {\r\n console.log(\"请指定 shell 类型:dskcode completion bash 或 dskcode completion zsh\");\r\n return;\r\n }\r\n if (shell === \"bash\") {\r\n console.log(`# dskcode bash 自动补全\r\n_dskcode_completion() {\r\n local cur=\\${COMP_WORDS[COMP_CWORD]}\r\n if [[ \\${COMP_CWORD} -eq 1 ]]; then\r\n COMPREPLY=( $(compgen -W \"${SUBCOMMANDS.join(\" \")}\" -- \"\\${cur}\") )\r\n return 0\r\n fi\r\n COMPREPLY=( $(compgen -W \"--verbose --config --model\" -- \"\\${cur}\") )\r\n}\r\ncomplete -F _dskcode_completion dskcode`);\r\n } else {\r\n console.log(`# dskcode zsh 自动补全\r\n_dskcode_completion() {\r\n local -a commands\r\n commands=(\r\n \"chat:启动交互式对话会话\"\r\n \"run:执行一次性任务\"\r\n \"setup:运行配置向导\"\r\n \"init:生成项目记忆文件\"\r\n \"completion:输出 shell 自动补全说明\"\r\n \"game:内置小游戏\"\r\n )\r\n _describe 'dskcode commands' commands\r\n}\r\ncompdef _dskcode_completion dskcode`);\r\n }\r\n });\r\n\r\n // game — 游戏模式\r\n initGames();\r\n\r\n program\r\n .command(\"game\")\r\n .description(\"启动内置小游戏\")\r\n .argument(\"[name]\", \"游戏名称,不指定则显示交互式游戏列表\")\r\n .action(async function (name?: string) {\r\n if (name) {\r\n const game = getGame(name);\r\n if (!game) {\r\n console.error(`未找到游戏 \"${name}\"。使用 dskcode game 查看可用游戏列表。`);\r\n process.exit(1);\r\n }\r\n console.log(`正在启动: ${game.name} — ${game.description}\\n`);\r\n await game.play();\r\n } else {\r\n const games = listGames();\r\n if (games.length === 0) {\r\n console.log(\"暂无可用游戏。\");\r\n return;\r\n }\r\n\r\n const selectedGame = await new Promise<Game | null>((resolve) => {\r\n const { unmount } = render(\r\n <GamePicker\r\n games={games}\r\n onSelect={(game) => {\r\n unmount();\r\n resolve(game);\r\n }}\r\n onExit={() => {\r\n unmount();\r\n resolve(null);\r\n }}\r\n />,\r\n );\r\n });\r\n\r\n if (selectedGame) {\r\n console.log(`\\n 启动游戏: ${chalk.green(selectedGame.name)}\\n`);\r\n await selectedGame.play();\r\n }\r\n }\r\n });\r\n\r\n return program;\r\n}\r\n","import type { Command } from \"commander\";\r\nimport type { Config } from \"../config/index.js\";\r\nimport { loadConfig } from \"../config/index.js\";\r\n\r\n/**\r\n * dskcode 运行时上下文。\r\n * 通过 commander 的 preAction hook 注入到每个命令中。\r\n */\r\nexport interface DskcodeContext {\r\n config: Config;\r\n verbose: boolean;\r\n}\r\n\r\n/**\r\n * 在 preAction hook 中加载配置并构造上下文。\r\n */\r\nexport async function loadConfigMiddleware(this: Command): Promise<DskcodeContext> {\r\n const opts = this.optsWithGlobals() as { verbose?: boolean; config?: string };\r\n const verbose = opts.verbose ?? false;\r\n\r\n let config: Config;\r\n try {\r\n config = await loadConfig(opts.config);\r\n } catch {\r\n const { defaultConfig } = await import(\"../config/index.js\");\r\n config = defaultConfig;\r\n }\r\n\r\n return { config, verbose };\r\n}\r\n","import type { Command } from \"commander\";\r\nimport chalk from \"chalk\";\r\n\r\nexport function customHelp(program: Command): string {\r\n const lines: string[] = [];\r\n\r\n lines.push(\"\");\r\n lines.push(chalk.bold(\"用法:\"));\r\n lines.push(` ${chalk.cyan(\"dskcode\")} ${chalk.dim(\"[global-options]\")} ${chalk.green(\"<command>\")} ${chalk.dim(\"[options]\")}`);\r\n lines.push(\"\");\r\n\r\n const globalOpts = program.options.filter(\r\n (o) => o.long !== \"--help\" && o.long !== \"--version\" && o.long !== \"--config\",\r\n );\r\n if (globalOpts.length > 0) {\r\n lines.push(chalk.bold(\"全局选项:\"));\r\n for (const opt of globalOpts) {\r\n const flags = [opt.short, opt.long].filter(Boolean).join(\", \");\r\n lines.push(` ${chalk.cyan(flags.padEnd(24))} ${opt.description ?? \"\"}`);\r\n }\r\n lines.push(\"\");\r\n }\r\n\r\n lines.push(chalk.bold(\"内置选项:\"));\r\n for (const flag of [\"-h, --help\", \"-V, --version\"]) {\r\n const opt = program.options.find(\r\n (o) => o.long === (flag.includes(\"help\") ? \"--help\" : \"--version\"),\r\n );\r\n if (opt) {\r\n lines.push(` ${chalk.cyan(flag.padEnd(24))} ${opt.description ?? \"\"}`);\r\n }\r\n }\r\n lines.push(\"\");\r\n\r\n const cmds = program.commands.filter((c) => !c.name().startsWith(\"help\"));\r\n if (cmds.length > 0) {\r\n lines.push(chalk.bold(\"命令:\"));\r\n for (const cmd of cmds) {\r\n lines.push(` ${chalk.green(cmd.name().padEnd(24))} ${cmd.description()}`);\r\n }\r\n lines.push(\"\");\r\n }\r\n\r\n lines.push(chalk.bold(\"示例:\"));\r\n lines.push(` ${chalk.dim(\"# 启动交互式对话\")}`);\r\n lines.push(\" dskcode chat\");\r\n lines.push(` ${chalk.dim(\"# 让 AI 执行一个任务\")}`);\r\n lines.push(\" dskcode run 修改所有 TODO 注释\");\r\n lines.push(` ${chalk.dim(\"# 运行配置向导\")}`);\r\n lines.push(\" dskcode setup\");\r\n lines.push(` ${chalk.dim(\"# 生成 shell 自动补全\")}`);\r\n lines.push(\" dskcode completion\");\r\n lines.push(\"\");\r\n\r\n return lines.join(\"\\n\");\r\n}\r\n","import { render } from \"ink\";\r\nimport type { ReactNode } from \"react\";\r\n\r\nexport interface RenderScopeHandle {\r\n waitUntilExit: Promise<unknown>;\r\n unmount: () => void;\r\n clear: () => void;\r\n}\r\n\r\nexport function renderApp(node: ReactNode): RenderScopeHandle {\r\n const { waitUntilExit, clear, unmount } = render(node);\r\n return { waitUntilExit: waitUntilExit(), clear, unmount };\r\n}\r\n\r\nexport async function unmountApp(handle: RenderScopeHandle): Promise<void> {\r\n handle.unmount();\r\n await new Promise((resolve) => setTimeout(resolve, 50));\r\n}\r\n","import { Text } from \"ink\";\r\nimport InkSpinner from \"ink-spinner\";\r\n\r\ninterface SpinnerProps {\r\n type?: \"dots\" | \"line\" | \"bouncingBar\" | \"aesthetic\";\r\n label?: string;\r\n}\r\n\r\nexport function Spinner({ type = \"dots\", label }: SpinnerProps) {\r\n return (\r\n <Text>\r\n <Text color=\"cyan\">\r\n <InkSpinner type={type} />\r\n </Text>\r\n {label ? <Text> {label}</Text> : null}\r\n </Text>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\n\r\ntype MessageType = \"info\" | \"success\" | \"warning\" | \"error\";\r\n\r\ninterface StatusMessageProps {\r\n type?: MessageType;\r\n label: string;\r\n detail?: string;\r\n}\r\n\r\nconst STYLES: Record<MessageType, { color: string; icon: string }> = {\r\n info: { color: \"cyan\", icon: \"ℹ\" },\r\n success: { color: \"green\", icon: \"✔\" },\r\n warning: { color: \"yellow\", icon: \"⚠\" },\r\n error: { color: \"red\", icon: \"✖\" },\r\n};\r\n\r\nexport function StatusMessage({ type = \"info\", label, detail }: StatusMessageProps) {\r\n const { color, icon } = STYLES[type];\r\n return (\r\n <Box>\r\n <Text color={color}>\r\n {icon} {label}\r\n </Text>\r\n {detail ? <Text dimColor>: {detail}</Text> : null}\r\n </Box>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\nimport { useEffect, useState } from \"react\";\r\n\r\nconst CYBER_PALETTE = [\"#00ffff\", \"#ff00ff\", \"#00ff41\", \"#ff1493\", \"#8b00ff\"];\r\n\r\nconst LOGO_LINES = [\r\n \" ██████╗ ███████╗██╗ ██╗\",\r\n \" ██╔══██╗██╔════╝██║ ██╔╝\",\r\n \" ██║ ██║███████╗█████╔╝ \",\r\n \" ██║ ██║╚════██║██╔═██╗ \",\r\n \" ██████╔╝███████║██║ ██╗\",\r\n \" ╚═════╝ ╚══════╝╚═╝ ╚═╝\",\r\n];\r\n\r\nexport function DskcodeSplash() {\r\n const [offset, setOffset] = useState(0);\r\n\r\n useEffect(() => {\r\n const timer = setInterval(() => {\r\n setOffset((prev) => (prev + 1) % CYBER_PALETTE.length);\r\n }, 500);\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n return (\r\n <Box flexDirection=\"column\" paddingLeft={1}>\r\n {LOGO_LINES.map((line, i) => {\r\n const colorIndex = (i + offset) % CYBER_PALETTE.length;\r\n return (\r\n <Box key={i}>\r\n <Text bold color={CYBER_PALETTE[colorIndex]}>\r\n {line}\r\n </Text>\r\n </Box>\r\n );\r\n })}\r\n </Box>\r\n );\r\n}\r\n","import { Box, Text } from \"ink\";\r\nimport TextInput from \"ink-text-input\";\r\nimport { useEffect, useState, useCallback } from \"react\";\r\n\r\nconst CYBER_PALETTE = [\"#00ffff\", \"#ff00ff\", \"#00ff41\", \"#ff1493\", \"#8b00ff\"];\r\n\r\nconst LOGO_LINES = [\r\n \" ██████╗ ███████╗██╗ ██╗\",\r\n \" ██╔══██╗██╔════╝██║ ██╔╝\",\r\n \" ██║ ██║███████╗█████╔╝ \",\r\n \" ██║ ██║╚════██║██╔═██╗ \",\r\n \" ██████╔╝███████║██║ ██╗\",\r\n \" ╚═════╝ ╚══════╝╚═╝ ╚═╝\",\r\n];\r\n\r\nconst COMMANDS: Record<string, { desc: string; handler: () => string }> = {\r\n \"/exit\": { desc: \"退出对话\", handler: () => \"\" },\r\n \"/quit\": { desc: \"退出对话\", handler: () => \"\" },\r\n \"/help\": {\r\n desc: \"显示帮助信息\",\r\n handler: () =>\r\n [\r\n \"可用命令:\",\r\n \" /exit, /quit 退出对话\",\r\n \" /help 显示此帮助\",\r\n \" /clear 清空对话历史\",\r\n \" /version 显示版本信息\",\r\n ].join(\"\\n\"),\r\n },\r\n \"/clear\": { desc: \"清空对话历史\", handler: () => \"\" },\r\n \"/version\": { desc: \"显示版本信息\", handler: () => \"dskcode v0.0.0\" },\r\n};\r\n\r\ninterface ChatMessage {\r\n role: \"user\" | \"assistant\";\r\n content: string;\r\n}\r\n\r\ninterface ChatSessionProps {\r\n providerCount: number;\r\n toolCount: number;\r\n verbose: boolean;\r\n}\r\n\r\nexport function ChatSession({ providerCount, toolCount, verbose }: ChatSessionProps) {\r\n const [offset, setOffset] = useState(0);\r\n const [messages, setMessages] = useState<ChatMessage[]>([]);\r\n const [input, setInput] = useState(\"\");\r\n\r\n useEffect(() => {\r\n const timer = setInterval(() => {\r\n setOffset((prev) => (prev + 1) % CYBER_PALETTE.length);\r\n }, 500);\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n const handleSubmit = useCallback((value: string) => {\r\n const trimmed = value.trim();\r\n if (!trimmed) return;\r\n\r\n if (trimmed.startsWith(\"/\")) {\r\n const cmd = COMMANDS[trimmed.toLowerCase()];\r\n if (cmd) {\r\n if (trimmed.toLowerCase() === \"/exit\" || trimmed.toLowerCase() === \"/quit\") {\r\n process.exit(0);\r\n return;\r\n }\r\n if (trimmed.toLowerCase() === \"/clear\") {\r\n setMessages([]);\r\n setInput(\"\");\r\n return;\r\n }\r\n const result = cmd.handler();\r\n if (result) {\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: result },\r\n ]);\r\n }\r\n setInput(\"\");\r\n return;\r\n }\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: `未知命令:${trimmed}。输入 /help 查看。` },\r\n ]);\r\n setInput(\"\");\r\n return;\r\n }\r\n\r\n setMessages((prev) => [\r\n ...prev,\r\n { role: \"user\", content: trimmed },\r\n { role: \"assistant\", content: \"dskcode AI — 待实现(第07章)。当前为 CLI 框架演示模式。\" },\r\n ]);\r\n setInput(\"\");\r\n }, []);\r\n\r\n return (\r\n <Box flexDirection=\"column\" paddingLeft={1} paddingRight={1}>\r\n {/* Logo + 状态栏 — 左右布局 */}\r\n <Box flexDirection=\"row\" marginBottom={1}>\r\n {/* Logo */}\r\n <Box flexDirection=\"column\" marginRight={4}>\r\n {LOGO_LINES.map((line, i) => {\r\n const colorIndex = (i + offset) % CYBER_PALETTE.length;\r\n return (\r\n <Box key={i}>\r\n <Text bold color={CYBER_PALETTE[colorIndex]}>\r\n {line}\r\n </Text>\r\n </Box>\r\n );\r\n })}\r\n </Box>\r\n\r\n {/* 状态信息 */}\r\n <Box flexDirection=\"column\" justifyContent=\"center\">\r\n <Text color=\"#00ff41\">{\" ✔ \"}已加载 {providerCount} 个 Provider</Text>\r\n <Text color=\"#00ffff\">{\" ℹ \"}已就绪 {toolCount} 个工具</Text>\r\n {verbose ? <Text color=\"#ff1493\">{\" ⚡ Verbose\"}</Text> : null}\r\n </Box>\r\n </Box>\r\n\r\n {/* Messages */}\r\n <Box flexDirection=\"column\" marginTop={1}>\r\n {messages.map((msg, i) => (\r\n <Box key={i} marginTop={1}>\r\n <Box width={8} flexShrink={0}>\r\n <Text bold color={msg.role === \"user\" ? \"#00ff41\" : \"#ff00ff\"}>\r\n {msg.role === \"user\" ? \" 👤\" : \" 🤖\"}\r\n </Text>\r\n </Box>\r\n <Box flexGrow={1}>\r\n <Text wrap=\"wrap\">{msg.content}</Text>\r\n </Box>\r\n </Box>\r\n ))}\r\n </Box>\r\n\r\n {/* Input */}\r\n <Box marginTop={1}>\r\n <Box width={8} flexShrink={0}>\r\n <Text bold color=\"#00ff41\">\r\n {\" ⚡\"}\r\n </Text>\r\n </Box>\r\n <Box flexGrow={1}>\r\n <TextInput\r\n value={input}\r\n onChange={setInput}\r\n onSubmit={handleSubmit}\r\n placeholder=\"输入你的问题...\"\r\n />\r\n </Box>\r\n </Box>\r\n\r\n <Box marginTop={1}>\r\n <Text color=\"#00ffff\" dimColor>\r\n {\" \" + \"─\".repeat(36)}\r\n </Text>\r\n </Box>\r\n </Box>\r\n );\r\n}\r\n","import { Box, Text, useInput } from \"ink\";\r\nimport { useState, useCallback } from \"react\";\r\nimport type { Game } from \"../game/index.js\";\r\n\r\ninterface GamePickerProps {\r\n games: Game[];\r\n onSelect: (game: Game) => void;\r\n onExit: () => void;\r\n}\r\n\r\nexport function GamePicker({ games, onSelect, onExit }: GamePickerProps) {\r\n const [selectedIndex, setSelectedIndex] = useState(0);\r\n\r\n useInput(\r\n useCallback(\r\n (input, key) => {\r\n if (games.length === 0) return;\r\n if (key.upArrow || input === \"k\") {\r\n setSelectedIndex((prev) => (prev > 0 ? prev - 1 : games.length - 1));\r\n } else if (key.downArrow || input === \"j\") {\r\n setSelectedIndex((prev) => (prev < games.length - 1 ? prev + 1 : 0));\r\n } else if (key.return) {\r\n const game = games[selectedIndex];\r\n if (game) onSelect(game);\r\n } else if (key.escape || input === \"q\") {\r\n onExit();\r\n }\r\n },\r\n [games, selectedIndex, onSelect, onExit],\r\n ),\r\n );\r\n\r\n return (\r\n <Box flexDirection=\"column\">\r\n <Box marginBottom={1}>\r\n <Text bold color=\"#00ffff\">\r\n 🎮 游戏列表\r\n </Text>\r\n </Box>\r\n\r\n <Box flexDirection=\"column\">\r\n {games.map((game, index) => {\r\n const isSelected = index === selectedIndex;\r\n return (\r\n <Box key={game.id} flexDirection=\"row\">\r\n <Box width={3} flexShrink={0}>\r\n {isSelected ? (\r\n <Text bold color=\"#00ff41\">\r\n {\"▸ \"}\r\n </Text>\r\n ) : (\r\n <Text>{\" \"}</Text>\r\n )}\r\n </Box>\r\n <Box width={20} flexShrink={0}>\r\n <Text bold color={isSelected ? \"#00ff41\" : \"#ffffff\"}>\r\n {game.name}\r\n </Text>\r\n </Box>\r\n <Box>\r\n <Text color=\"#888888\">{game.description}</Text>\r\n </Box>\r\n </Box>\r\n );\r\n })}\r\n </Box>\r\n\r\n <Box marginTop={1}>\r\n <Text dimColor>\r\n {\" ↑/↓ 选择 Enter 启动 q 返回\"}\r\n </Text>\r\n </Box>\r\n </Box>\r\n );\r\n}\r\n","export interface Game {\r\n /** 游戏唯一标识 */\r\n id: string;\r\n /** 游戏名称 */\r\n name: string;\r\n /** 简短描述 */\r\n description: string;\r\n /** 启动游戏 */\r\n play: () => Promise<void>;\r\n}\r\n\r\nconst registry = new Map<string, Game>();\r\n\r\nexport function registerGame(game: Game): void {\r\n registry.set(game.id, game);\r\n}\r\n\r\nexport function getGame(id: string): Game | undefined {\r\n return registry.get(id);\r\n}\r\n\r\nexport function listGames(): Game[] {\r\n return Array.from(registry.values());\r\n}\r\n","import { Box, Text, useInput, render } from \"ink\";\r\nimport { useState, useEffect, useRef, useCallback } from \"react\";\r\n\r\nconst GAME_WIDTH = 40;\r\nconst GAME_HEIGHT = 18;\r\nconst PADDLE_WIDTH = 9;\r\nconst BRICK_COLORS = [166, 214, 76, 69];\r\n\r\ninterface Vec2 {\r\n x: number;\r\n y: number;\r\n}\r\n\r\ninterface Brick {\r\n x: number;\r\n y: number;\r\n w: number;\r\n alive: boolean;\r\n}\r\n\r\n// ─── 10 个关卡定义 ──────────────────────────────────────────────\r\n\r\ninterface LevelDef {\r\n rows: number;\r\n cols: number;\r\n bw: number; // 砖块宽度(格数)\r\n desc: string;\r\n // 返回 true 表示该位置有砖块\r\n pattern: (col: number, row: number, rows: number, cols: number) => boolean;\r\n}\r\n\r\nconst LEVELS: LevelDef[] = [\r\n { rows: 4, cols: 8, bw: 3, desc: \"经典 4×8\", pattern: () => true },\r\n { rows: 3, cols: 8, bw: 3, desc: \"轻松 3 层\", pattern: () => true },\r\n { rows: 6, cols: 8, bw: 3, desc: \"厚墙 6 层\", pattern: () => true },\r\n { rows: 4, cols: 8, bw: 3, desc: \"棋盘格\", pattern: (c, r) => (c + r) % 2 === 0 },\r\n { rows: 4, cols: 8, bw: 3, desc: \"金字塔\", pattern: (c, r, _, tc) => c >= r && c < tc - r },\r\n { rows: 4, cols: 8, bw: 3, desc: \"交错排列\", pattern: (c, r) => r % 2 === 0 || (c >= 1 && c <= 6) },\r\n { rows: 4, cols: 8, bw: 3, desc: \"中空边框\", pattern: (c, r, tr, tc) => r === 0 || r === tr - 1 || c === 0 || c === tc - 1 },\r\n { rows: 4, cols: 10, bw: 2, desc: \"密集 10 列\", pattern: () => true },\r\n { rows: 7, cols: 8, bw: 3, desc: \"高墙 7 层\", pattern: () => true },\r\n { rows: 8, cols: 8, bw: 3, desc: \"满屏 8 层\", pattern: () => true },\r\n];\r\n\r\nfunction getLevel(level: number): LevelDef {\r\n return LEVELS[(level - 1) % LEVELS.length] as LevelDef;\r\n}\r\n\r\nfunction createBricks(level: number): Brick[] {\r\n const def = getLevel(level);\r\n const bricks: Brick[] = [];\r\n const gap = 2;\r\n const totalW = def.cols * def.bw + (def.cols - 1) * gap;\r\n const startX = Math.floor((GAME_WIDTH - totalW) / 2);\r\n const step = def.bw + gap;\r\n\r\n for (let row = 0; row < def.rows; row++) {\r\n for (let col = 0; col < def.cols; col++) {\r\n if (def.pattern(col, row, def.rows, def.cols)) {\r\n bricks.push({\r\n x: startX + col * step,\r\n y: 2 + row * 2,\r\n w: def.bw,\r\n alive: true,\r\n });\r\n }\r\n }\r\n }\r\n return bricks;\r\n}\r\n\r\n// ─── 游戏状态 ──────────────────────────────────────────────────\r\n\r\ninterface GameState {\r\n level: number;\r\n bricks: Brick[];\r\n paddleX: number;\r\n ball: Vec2;\r\n ballDir: Vec2;\r\n score: number;\r\n lives: number;\r\n gameOver: boolean;\r\n win: boolean;\r\n paused: boolean;\r\n}\r\n\r\nfunction createInitialState(level: number): GameState {\r\n const def = getLevel(level);\r\n const totalW = def.cols * def.bw + (def.cols - 1) * 2;\r\n const startX = Math.floor((GAME_WIDTH - totalW) / 2);\r\n return {\r\n level,\r\n bricks: createBricks(level),\r\n paddleX: Math.floor(GAME_WIDTH / 2) - Math.floor(PADDLE_WIDTH / 2),\r\n ball: { x: GAME_WIDTH / 2, y: GAME_HEIGHT - 3 },\r\n ballDir: { x: 1, y: -1 },\r\n score: 0,\r\n lives: 3,\r\n gameOver: false,\r\n win: false,\r\n paused: false,\r\n };\r\n}\r\n\r\n// ─── 物理更新 ──────────────────────────────────────────────────\r\n\r\nfunction update(state: GameState): void {\r\n if (state.paused || state.gameOver || state.win) return;\r\n\r\n state.ball.x += state.ballDir.x;\r\n state.ball.y += state.ballDir.y;\r\n\r\n if (state.ball.x <= 0) { state.ball.x = 0; state.ballDir.x = 1; }\r\n if (state.ball.x >= GAME_WIDTH - 1) { state.ball.x = GAME_WIDTH - 1; state.ballDir.x = -1; }\r\n if (state.ball.y <= 0) { state.ball.y = 0; state.ballDir.y = 1; }\r\n\r\n // 挡板碰撞\r\n if (\r\n state.ball.y === GAME_HEIGHT - 1 &&\r\n state.ball.x >= state.paddleX &&\r\n state.ball.x <= state.paddleX + PADDLE_WIDTH\r\n ) {\r\n state.ballDir.y = -1;\r\n const hitPos = (state.ball.x - state.paddleX) / PADDLE_WIDTH;\r\n state.ballDir.x = hitPos < 0.5 ? -1 : 1;\r\n }\r\n\r\n // 出界\r\n if (state.ball.y > GAME_HEIGHT) {\r\n state.lives--;\r\n if (state.lives <= 0) {\r\n state.gameOver = true;\r\n } else {\r\n state.ball = { x: GAME_WIDTH / 2, y: GAME_HEIGHT - 3 };\r\n state.ballDir = { x: 1, y: -1 };\r\n state.paddleX = Math.floor(GAME_WIDTH / 2) - Math.floor(PADDLE_WIDTH / 2);\r\n }\r\n }\r\n\r\n // 砖块碰撞\r\n const hitBrick = state.bricks.find((b) => {\r\n if (!b.alive) return false;\r\n return state.ball.x >= b.x && state.ball.x < b.x + b.w && state.ball.y >= b.y && state.ball.y < b.y + 1;\r\n });\r\n\r\n if (hitBrick) {\r\n hitBrick.alive = false;\r\n state.score += 10;\r\n state.ballDir.y = -state.ballDir.y;\r\n }\r\n\r\n if (state.bricks.every((b) => !b.alive)) state.win = true;\r\n}\r\n\r\n// ─── 画面渲染(含 ANSI 颜色) ─────────────────────────────────\r\n\r\nfunction buildBoard(state: GameState): string {\r\n const lines: string[] = [];\r\n\r\n function brickColorIndex(x: number, y: number): number | undefined {\r\n const row = Math.floor((y - 2) / 2);\r\n if (row >= 0) {\r\n const b = state.bricks.find((br) => br.y === y && br.alive && x >= br.x && x < br.x + br.w);\r\n if (b) return row % BRICK_COLORS.length;\r\n }\r\n return undefined;\r\n }\r\n\r\n for (let y = 0; y < GAME_HEIGHT; y++) {\r\n let line = \"\";\r\n for (let x = 0; x < GAME_WIDTH; x++) {\r\n const isBall = state.ball.x === x && state.ball.y === y;\r\n const isPaddle = y === GAME_HEIGHT - 1 && x >= state.paddleX && x < state.paddleX + PADDLE_WIDTH;\r\n const brickRow = brickColorIndex(x, y);\r\n\r\n if (isBall) {\r\n line += \"\\x1b[97m●\\x1b[0m\";\r\n } else if (isPaddle) {\r\n line += \"\\x1b[94m▄\\x1b[0m\";\r\n } else if (brickRow !== undefined) {\r\n line += `\\x1b[38;5;${BRICK_COLORS[brickRow] as number}m▀\\x1b[0m`;\r\n } else {\r\n line += \" \";\r\n }\r\n }\r\n lines.push(line);\r\n }\r\n\r\n return lines.map((l) => `│${l}│`).join(\"\\n\");\r\n}\r\n\r\n// ─── Ink 组件 ──────────────────────────────────────────────────\r\n\r\ninterface BrickBreakerGameProps {\r\n onExit: () => void;\r\n}\r\n\r\nfunction BrickBreakerGame({ onExit: _onExit }: BrickBreakerGameProps) {\r\n const [initialLevel, setInitialLevel] = useState(1);\r\n const [selectingLevel, setSelectingLevel] = useState(true);\r\n const stateRef = useRef<GameState>(createInitialState(initialLevel));\r\n const [tick, setTick] = useState(0);\r\n const onExitRef = useRef(_onExit);\r\n onExitRef.current = _onExit;\r\n\r\n useEffect(() => {\r\n if (selectingLevel) return;\r\n const interval = setInterval(() => {\r\n update(stateRef.current);\r\n setTick((t) => t + 1);\r\n }, 80);\r\n return () => clearInterval(interval);\r\n }, [selectingLevel]);\r\n\r\n // 重新开始(保留当前关卡)\r\n const restart = useCallback((level?: number) => {\r\n const lv = level ?? stateRef.current.level;\r\n stateRef.current = createInitialState(lv);\r\n setInitialLevel(lv);\r\n setSelectingLevel(false);\r\n setTick(0);\r\n }, []);\r\n\r\n // 选关\r\n const startLevelSelect = useCallback(() => {\r\n setSelectingLevel(true);\r\n }, []);\r\n\r\n useInput(\r\n useCallback((input, key) => {\r\n const s = stateRef.current;\r\n\r\n // 选关模式\r\n if (selectingLevel) {\r\n if (input >= \"1\" && input <= \"9\") {\r\n restart(Number(input));\r\n } else if (input === \"0\") {\r\n restart(10);\r\n } else if (key.escape || input === \"q\") {\r\n onExitRef.current();\r\n }\r\n return;\r\n }\r\n\r\n if (key.leftArrow) {\r\n s.paddleX = Math.max(0, s.paddleX - 1);\r\n setTick((t) => t + 1);\r\n } else if (key.rightArrow) {\r\n s.paddleX = Math.min(GAME_WIDTH - PADDLE_WIDTH, s.paddleX + 1);\r\n setTick((t) => t + 1);\r\n } else if (input === \"p\" || input === \" \") {\r\n s.paused = !s.paused;\r\n } else if (input === \"r\") {\r\n if (s.gameOver || s.win) restart();\r\n } else if (input === \"l\") {\r\n if (s.gameOver || s.win) startLevelSelect();\r\n } else if (input === \"q\" || key.escape) {\r\n onExitRef.current();\r\n }\r\n }, [selectingLevel, restart, startLevelSelect]),\r\n );\r\n\r\n const s = stateRef.current;\r\n const aliveCount = s.bricks.filter((b) => b.alive).length;\r\n const board = buildBoard(s);\r\n const def = getLevel(s.level);\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n void tick;\r\n\r\n return (\r\n <Box flexDirection=\"column\">\r\n {/* 状态栏 */}\r\n <Box flexDirection=\"row\">\r\n <Box width={20}>\r\n <Text>\r\n 关卡 {s.level}: <Text color=\"cyan\">{def.desc}</Text>\r\n </Text>\r\n </Box>\r\n <Box width={12}>\r\n <Text>\r\n 分数: <Text color=\"yellow\">{String(s.score).padStart(3, \"0\")}</Text>\r\n </Text>\r\n </Box>\r\n <Box width={12}>\r\n <Text>\r\n 生命: <Text color=\"red\">{\"♥\".repeat(Math.max(0, s.lives))}</Text>\r\n </Text>\r\n </Box>\r\n <Box width={10}>\r\n <Text>\r\n 砖块: <Text color=\"cyan\">{aliveCount}</Text>\r\n </Text>\r\n </Box>\r\n <Box>\r\n <Text color={s.paused ? \"gray\" : \"green\"}>\r\n [{s.paused ? \"暂停\" : \"运行中\"}]\r\n </Text>\r\n </Box>\r\n </Box>\r\n\r\n {/* 游戏画面 */}\r\n <Box flexDirection=\"column\">\r\n <Text>┌{\"─\".repeat(GAME_WIDTH)}┐</Text>\r\n <Text>{selectingLevel ? \" \\x1b[90m选择关卡后开始...\\x1b[0m\" : board}</Text>\r\n <Text>└{\"─\".repeat(GAME_WIDTH)}┘</Text>\r\n </Box>\r\n\r\n {/* 选关界面 */}\r\n {selectingLevel && (\r\n <Box marginTop={1} flexDirection=\"column\">\r\n <Text bold color=\"yellow\">选择关卡</Text>\r\n <Box flexDirection=\"row\" flexWrap=\"wrap\">\r\n {LEVELS.map((lv, i) => (\r\n <Box key={i} width={22}>\r\n <Text>\r\n <Text color={initialLevel === i + 1 ? \"green\" : \"white\"}>\r\n {i + 1 === 10 ? \"0\" : String(i + 1)}\r\n </Text>\r\n . {lv.desc} ({lv.rows}×{lv.cols})\r\n </Text>\r\n </Box>\r\n ))}\r\n </Box>\r\n <Box marginTop={1}>\r\n <Text dimColor>按数字选关 q 退出</Text>\r\n </Box>\r\n </Box>\r\n )}\r\n\r\n {/* 结束/通关信息 */}\r\n {!selectingLevel && (s.gameOver || s.win) && (\r\n <Box marginTop={1}>\r\n <Text bold color={s.gameOver ? \"red\" : \"green\"}>\r\n {s.gameOver ? \"游戏结束!\" : \"恭喜通关!\"}\r\n </Text>\r\n <Text>\r\n {\" 分数: \"}<Text color=\"yellow\">{s.score}</Text>\r\n </Text>\r\n </Box>\r\n )}\r\n\r\n {/* 操作提示 */}\r\n {!selectingLevel && (\r\n <Box marginTop={1}>\r\n {s.gameOver || s.win ? (\r\n <Text dimColor>\r\n {\"← → 移动 r 重开 l 选关 q 退出\"}\r\n </Text>\r\n ) : (\r\n <Text dimColor>\r\n {\"← → 移动 p 暂停 q 退出\"}\r\n </Text>\r\n )}\r\n </Box>\r\n )}\r\n </Box>\r\n );\r\n}\r\n\r\n// ─── 导出 ──────────────────────────────────────────────────────\r\n\r\nexport default {\r\n id: \"brick-breaker\",\r\n name: \"Brick Breaker\",\r\n description: \"经典打砖块游戏,10 个关卡可选!\",\r\n play: async () => {\r\n await new Promise<void>((resolve) => {\r\n const { unmount } = render(\r\n <BrickBreakerGame onExit={() => { unmount(); resolve(); }} />,\r\n );\r\n });\r\n },\r\n};\r\n","import { Box, Text, useInput, render } from \"ink\";\r\nimport { useState, useEffect, useRef, useCallback } from \"react\";\r\n\r\nconst GAME_W = 66;\r\nconst GAME_H = 20; // 6 行分数 + 14 行掉落单词\r\nconst SCORE_H = 6;\r\nconst WORD_H = 14;\r\nconst MAX_WORDS = 10;\r\nconst CYBER_PALETTE = [\"#00ffff\", \"#ff00ff\", \"#00ff41\", \"#ff1493\", \"#8b00ff\"];\r\n\r\n// 3×5 像素大号数字(每个像素 = ██,每数字 6 列)\r\nconst DIGIT_ART: Record<string, string[]> = {\r\n \"0\": [\" ██████ \", \"██ ██\", \"██ ██\", \"██ ██\", \" ██████ \"],\r\n \"1\": [\" ██ \", \" ████ \", \" ██ \", \" ██ \", \" ██████ \"],\r\n \"2\": [\" ██████ \", \" ██ \", \" ██████ \", \" ██ \", \" ██████ \"],\r\n \"3\": [\" ██████ \", \" ██ \", \" ██████ \", \" ██ \", \" ██████ \"],\r\n \"4\": [\"██ ██\", \"██ ██\", \" ██████ \", \" ██ \", \" ██ \"],\r\n \"5\": [\" ██████ \", \" ██ \", \" ██████ \", \" ██ \", \" ██████ \"],\r\n \"6\": [\" ██████ \", \" ██ \", \" ██████ \", \" ██ ██\", \" ██████ \"],\r\n \"7\": [\" ██████ \", \" ██ \", \" ██ \", \" ██ \", \" ██ \"],\r\n \"8\": [\" ██████ \", \"██ ██\", \" ██████ \", \"██ ██\", \" ██████ \"],\r\n \"9\": [\" ██████ \", \"██ ██\", \" ██████ \", \" ██ \", \" ██████ \"],\r\n};\r\n\r\nfunction buildScoreLines(scoreStr: string): string[] {\r\n const lines = [\"\", \"\", \"\", \"\", \"\"];\r\n for (const ch of scoreStr) {\r\n const art = DIGIT_ART[ch] ?? DIGIT_ART[\"0\"]!;\r\n for (let r = 0; r < 5; r++) {\r\n lines[r] += \" \" + (art[r] ?? \"\");\r\n }\r\n }\r\n // 左右各留 6 格间距\r\n const pad = 6;\r\n return lines.map((l) => \" \".repeat(pad) + l);\r\n}\r\n\r\nfunction hexToRgb(hex: string): string {\r\n const r = parseInt(hex.slice(1, 3), 16);\r\n const g = parseInt(hex.slice(3, 5), 16);\r\n const b = parseInt(hex.slice(5, 7), 16);\r\n return `${r};${g};${b}`;\r\n}\r\n\r\n// ─── 200 个常见单词 ────────────────────────────────────────────\r\n\r\nconst WORDS_BANK = [\r\n // ── 框架 & 库 ──\r\n \"react\", \"vue\", \"next\", \"node\", \"axios\", \"express\", \"lodash\", \"jquery\",\r\n \"webpack\", \"vite\", \"babel\", \"eslint\", \"prettier\", \"tailwind\", \"bootstrap\",\r\n \"sass\", \"less\", \"postcss\", \"redux\", \"pinia\", \"vuex\", \"router\",\r\n \"nestjs\", \"socket\", \"graphql\", \"rest\", \"grpc\", \"prisma\", \"typeorm\",\r\n\r\n // ── 前端 ──\r\n \"html\", \"css\", \"jsx\", \"tsx\", \"dom\", \"spa\", \"ssr\", \"csr\", \"pwa\",\r\n \"component\", \"prop\", \"hook\", \"composable\", \"directive\", \"filter\", \"mixin\",\r\n \"template\", \"render\", \"virtual\", \"diff\", \"patch\", \"hydration\",\r\n \"responsive\", \"flexbox\", \"grid\", \"animation\", \"transition\",\r\n\r\n // ── 后端 ──\r\n \"api\", \"route\", \"middleware\", \"controller\", \"service\", \"module\",\r\n \"dto\", \"entity\", \"schema\", \"migration\", \"seeder\", \"factory\",\r\n \"auth\", \"jwt\", \"oauth\", \"session\", \"cookie\", \"token\", \"cors\",\r\n \"cache\", \"redis\", \"mq\", \"rabbit\", \"kafka\", \"nats\",\r\n\r\n // ── 数据库 ──\r\n \"sql\", \"mysql\", \"pg\", \"sqlite\", \"mongo\", \"redis\", \"orm\",\r\n \"table\", \"index\", \"query\", \"join\", \"union\", \"group\", \"order\",\r\n \"where\", \"having\", \"limit\", \"offset\", \"insert\", \"update\", \"delete\",\r\n\r\n // ── DevOps ──\r\n \"docker\", \"nginx\", \"linux\", \"bash\", \"shell\", \"yaml\", \"toml\",\r\n \"ci\", \"cd\", \"deploy\", \"rollback\", \"release\", \"build\", \"test\",\r\n \"lint\", \"format\", \"stage\", \"commit\", \"branch\", \"merge\", \"rebase\",\r\n\r\n // ── 数据结构 & 算法 ──\r\n \"array\", \"stack\", \"queue\", \"tree\", \"graph\", \"list\", \"map\", \"set\",\r\n \"sort\", \"search\", \"filter\", \"reduce\", \"map\", \"async\", \"await\",\r\n \"promise\", \"callback\", \"closure\", \"proxy\", \"reflect\", \"decorator\",\r\n\r\n // ── 常用操作 ──\r\n \"create\", \"read\", \"update\", \"delete\", \"crud\", \"parse\", \"stringify\",\r\n \"encode\", \"decode\", \"transform\", \"validate\", \"format\", \"parse\",\r\n \"upload\", \"download\", \"export\", \"import\", \"backup\", \"restore\",\r\n\r\n // ── 类型 & 变量 ──\r\n \"string\", \"number\", \"boolean\", \"object\", \"array\", \"tuple\", \"enum\",\r\n \"interface\", \"type\", \"class\", \"function\", \"method\", \"property\",\r\n \"public\", \"private\", \"static\", \"readonly\", \"optional\", \"abstract\",\r\n \"const\", \"let\", \"var\", \"void\", \"null\", \"undef\", \"never\", \"any\",\r\n\r\n // ── 补充 ──\r\n \"config\", \"logger\", \"monitor\", \"metric\", \"alert\", \"webhook\",\r\n \"endpoint\", \"payload\", \"header\", \"status\", \"timeout\", \"retry\",\r\n \"fallback\", \"circuit\", \"breaker\", \"throttle\", \"debounce\",\r\n \"scroll\", \"resize\", \"click\", \"hover\", \"focus\", \"blur\",\r\n];\r\n\r\nfunction randomWord(used: Set<string>): string {\r\n let w: string;\r\n do { w = WORDS_BANK[Math.floor(Math.random() * WORDS_BANK.length)] as string; }\r\n while (used.has(w));\r\n return w;\r\n}\r\n\r\n// ─── 游戏状态 ──────────────────────────────────────────────────\r\n\r\ninterface DropWord {\r\n text: string;\r\n row: number;\r\n col: number;\r\n}\r\n\r\ninterface GameState {\r\n words: DropWord[];\r\n score: number;\r\n lives: number;\r\n speed: number;\r\n spawnTimer: number;\r\n gameOver: boolean;\r\n paused: boolean;\r\n typed: string;\r\n target: string | null;\r\n combo: number;\r\n message: string;\r\n messageTimer: number;\r\n usedWords: Set<string>;\r\n}\r\n\r\nfunction createInitialState(): GameState {\r\n return {\r\n words: [],\r\n score: 0,\r\n lives: 3,\r\n speed: 0.3,\r\n spawnTimer: 0,\r\n gameOver: false,\r\n paused: false,\r\n typed: \"\",\r\n target: null,\r\n combo: 0,\r\n message: \"\",\r\n messageTimer: 0,\r\n usedWords: new Set(),\r\n };\r\n}\r\n\r\nfunction pickTarget(s: GameState): string | null {\r\n // 选取最靠左的存活单词作为目标\r\n let best: DropWord | null = null;\r\n for (const w of s.words) {\r\n if (!best || w.col < best.col) best = w;\r\n }\r\n return best?.text ?? null;\r\n}\r\n\r\n// ─── 物理更新 ──────────────────────────────────────────────────\r\n\r\nfunction update(s: GameState): void {\r\n if (s.paused || s.gameOver) return;\r\n\r\n // 生成新单词\r\n s.spawnTimer++;\r\n if (s.spawnTimer >= Math.max(20, 50 - Math.floor(s.speed * 15))) {\r\n s.spawnTimer = 0;\r\n if (s.words.length < MAX_WORDS) {\r\n const used = new Set(s.usedWords);\r\n for (const w of s.words) used.add(w.text);\r\n const text = randomWord(used);\r\n // 找空白行\r\n const usedRows = new Set(s.words.map((w) => w.row));\r\n let row = -1;\r\n for (let r = SCORE_H; r < GAME_H; r++) {\r\n if (!usedRows.has(r)) { row = r; break; }\r\n }\r\n if (row >= 0) {\r\n s.words.push({ text, row, col: GAME_W - 1 });\r\n s.usedWords.add(text);\r\n }\r\n }\r\n }\r\n\r\n // 移动单词\r\n for (const w of s.words) {\r\n w.col -= s.speed;\r\n }\r\n\r\n // 移除超出左边的 + 更新目标\r\n const before = s.words.length;\r\n s.words = s.words.filter((w) => w.col > -w.text.length);\r\n const removed = before - s.words.length;\r\n\r\n // 单词漏掉了 → 扣命\r\n if (removed > 0) {\r\n s.lives -= removed;\r\n s.typed = \"\";\r\n s.target = pickTarget(s);\r\n if (s.lives <= 0) {\r\n s.gameOver = true;\r\n s.words = [];\r\n }\r\n }\r\n\r\n // 更新目标\r\n s.target = pickTarget(s);\r\n\r\n // 消息计时\r\n if (s.messageTimer > 0) {\r\n s.messageTimer--;\r\n if (s.messageTimer <= 0) s.message = \"\";\r\n }\r\n}\r\n\r\n// ─── 画面渲染 ──────────────────────────────────────────────────\r\n\r\nfunction buildGameView(s: GameState, scoreLines: string[], scoreColor: string, message: string): string[] {\r\n const rows: string[] = [];\r\n\r\n for (let y = 0; y < GAME_H; y++) {\r\n let line = \"\";\r\n\r\n // 分数区域(前 6 行)\r\n if (y < SCORE_H) {\r\n if (y < 5) {\r\n // 数字行 — 先补足宽度再套赛博朋克色\r\n const raw = (scoreLines[y] ?? \"\").padEnd(GAME_W);\r\n line = `\\x1b[38;2;${hexToRgb(scoreColor)}m${raw}\\x1b[0m`;\r\n } else if (y === 5) {\r\n // 第 6 行:连击 / 暂停\r\n if (s.combo >= 3) {\r\n const comboText = `${s.combo}连击!`;\r\n const pad = Math.floor((GAME_W - comboText.length) / 2);\r\n const comboColor = CYBER_PALETTE[s.combo % CYBER_PALETTE.length] as string;\r\n const raw = \" \".repeat(pad) + comboText + \" \".repeat(GAME_W - pad - comboText.length);\r\n line = `\\x1b[38;2;${hexToRgb(comboColor)}m${raw}\\x1b[0m`;\r\n } else if (s.paused) {\r\n const pauseText = \"暂停\";\r\n const pad = Math.floor((GAME_W - pauseText.length) / 2);\r\n line = \" \".repeat(pad) + pauseText;\r\n line = line.padEnd(GAME_W);\r\n }\r\n }\r\n // 补全到 GAME_W 宽度\r\n line = line.padEnd(GAME_W);\r\n } else {\r\n // 单词区域\r\n // 第 1 行显示消息(如果有)\r\n if (y === SCORE_H && message) {\r\n const pad = Math.floor((GAME_W - message.length) / 2);\r\n const raw = \" \".repeat(pad) + message + \" \".repeat(GAME_W - pad - message.length);\r\n const msgColor = CYBER_PALETTE[Math.floor(Math.random() * CYBER_PALETTE.length)] as string;\r\n line = `\\x1b[38;2;${hexToRgb(msgColor)}m${raw}\\x1b[0m`;\r\n } else {\r\n for (let x = 0; x < GAME_W; x++) {\r\n const word = s.words.find((w) => {\r\n const charIdx = x - Math.floor(w.col);\r\n return charIdx >= 0 && charIdx < w.text.length && w.row === y;\r\n });\r\n if (word) {\r\n const charIdx = x - Math.floor(word.col);\r\n const ch = word.text[charIdx] as string;\r\n const isTarget = word.text === s.target;\r\n const typedIdx = s.target === word.text ? s.typed.length : 0;\r\n const isTyped = isTarget && charIdx < typedIdx;\r\n if (isTarget) {\r\n line += isTyped ? `\\x1b[92m${ch}\\x1b[0m` : `\\x1b[97m${ch}\\x1b[0m`;\r\n } else {\r\n line += `\\x1b[90m${ch}\\x1b[0m`;\r\n }\r\n } else {\r\n line += \" \";\r\n }\r\n }\r\n }\r\n }\r\n\r\n rows.push(line);\r\n }\r\n return rows;\r\n}\r\n\r\n// ─── Ink 组件 ──────────────────────────────────────────────────\r\n\r\ninterface CoderCheckProps {\r\n onExit: () => void;\r\n}\r\n\r\nfunction CoderCheck({ onExit: _onExit }: CoderCheckProps) {\r\n const stateRef = useRef<GameState>(createInitialState());\r\n const [tick, setTick] = useState(0);\r\n const [colorOffset, setColorOffset] = useState(0);\r\n const onExitRef = useRef(_onExit);\r\n onExitRef.current = _onExit;\r\n\r\n // 赛博朋克颜色动画\r\n useEffect(() => {\r\n const timer = setInterval(() => {\r\n setColorOffset((prev) => (prev + 1) % CYBER_PALETTE.length);\r\n }, 400);\r\n return () => clearInterval(timer);\r\n }, []);\r\n\r\n // 游戏循环\r\n useEffect(() => {\r\n const interval = setInterval(() => {\r\n update(stateRef.current);\r\n setTick((t) => t + 1);\r\n }, 60);\r\n return () => clearInterval(interval);\r\n }, []);\r\n\r\n useInput(\r\n useCallback((input, key) => {\r\n const s = stateRef.current;\r\n if (s.gameOver) {\r\n if (input === \"r\") {\r\n stateRef.current = createInitialState();\r\n setTick(0);\r\n } else if (input === \"q\" || key.escape) {\r\n onExitRef.current();\r\n }\r\n return;\r\n }\r\n\r\n if ((input === \"p\" && key.ctrl) || input === \" \") {\r\n s.paused = !s.paused;\r\n return;\r\n }\r\n if ((input === \"q\" && key.ctrl) || key.escape) {\r\n onExitRef.current();\r\n return;\r\n }\r\n\r\n if (s.paused) return;\r\n\r\n // 打字输入\r\n if (input.length === 1 && input >= \"a\" && input <= \"z\") {\r\n // 选取目标\r\n if (!s.target) {\r\n s.target = pickTarget(s);\r\n }\r\n if (s.target) {\r\n const nextChar = s.target[s.typed.length];\r\n if (nextChar === input) {\r\n s.typed += input;\r\n // 检查是否完成\r\n if (s.typed === s.target) {\r\n // 移除该单词\r\n s.words = s.words.filter((w) => w.text !== s.target);\r\n s.combo++;\r\n // 连击 >= 3 时以当前分数翻倍奖励\r\n const prevScore = s.score;\r\n const basePts = s.target.length;\r\n const comboBonus = s.combo >= 3 ? s.score : 0;\r\n s.score += basePts + comboBonus;\r\n s.speed = s.speed + 0.02;\r\n\r\n // 每 500 分提速\r\n const prevMilestone = Math.floor(prevScore / 500);\r\n const newMilestone = Math.floor(s.score / 500);\r\n if (newMilestone > prevMilestone) {\r\n s.speed += 0.15;\r\n }\r\n\r\n // 超过 99999 分提示通关\r\n if (s.score >= 100000 && prevScore < 100000) {\r\n s.message = \"恭喜通关! 难度最大化!\";\r\n s.messageTimer = 100;\r\n }\r\n s.typed = \"\";\r\n s.target = pickTarget(s);\r\n }\r\n } else {\r\n // 打错字符,连击中断\r\n s.combo = 0;\r\n }\r\n }\r\n }\r\n }, []),\r\n );\r\n\r\n const s = stateRef.current;\r\n const scoreColor = CYBER_PALETTE[colorOffset] as string;\r\n const scoreStr = String(s.score).padStart(5, \"0\");\r\n const scoreLines = buildScoreLines(scoreStr);\r\n const view = buildGameView(s, scoreLines, scoreColor, s.message);\r\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\r\n void tick;\r\n\r\n return (\r\n <Box flexDirection=\"column\" paddingX={1}>\r\n {/* 顶栏:生命 + 速度 */}\r\n <Box flexDirection=\"row\">\r\n <Text>\r\n 生命 <Text color=\"red\">{\"♥\".repeat(Math.max(0, s.lives))}</Text>\r\n {\" \"}速度 <Text color=\"cyan\">Lv.{Math.floor(s.speed * 10)}</Text>\r\n </Text>\r\n </Box>\r\n\r\n {/* 目标单词提示 */}\r\n {!s.gameOver && s.target && (\r\n <Box marginTop={1}>\r\n <Text>\r\n 打字: <Text color=\"green\">{s.typed}</Text>\r\n <Text color=\"white\">{s.target.slice(s.typed.length)}</Text>\r\n </Text>\r\n </Box>\r\n )}\r\n\r\n {/* 游戏画面(含分数) */}\r\n <Box flexDirection=\"column\" marginTop={1}>\r\n <Text>┌{\"─\".repeat(GAME_W)}┐</Text>\r\n {view.map((row, i) => (\r\n <Text key={i}>{`│${row}│`}</Text>\r\n ))}\r\n <Text>└{\"─\".repeat(GAME_W)}┘</Text>\r\n </Box>\r\n\r\n {/* 游戏结束 */}\r\n {s.gameOver && (\r\n <Box marginTop={1}>\r\n <Text bold color=\"red\">\r\n 游戏结束!\r\n </Text>\r\n <Text>\r\n {\" 得分: \"}<Text color=\"yellow\">{s.score}</Text>\r\n {\" r 重开 q 退出\"}\r\n </Text>\r\n </Box>\r\n )}\r\n\r\n {/* 操作提示 */}\r\n <Box marginTop={1}>\r\n <Text dimColor>\r\n {\"打字消除单词 空格/Ctrl+P暂停 Ctrl+Q退出\"}\r\n </Text>\r\n </Box>\r\n </Box>\r\n );\r\n}\r\n\r\n// ─── 导出 ──────────────────────────────────────────────────────\r\n\r\nexport default {\r\n id: \"coder-check\",\r\n name: \"Coder Check\",\r\n description: \"极速打字游戏,输入单词消除它们!\",\r\n play: async () => {\r\n await new Promise<void>((resolve) => {\r\n const { unmount } = render(\r\n <CoderCheck onExit={() => { unmount(); resolve(); }} />,\r\n );\r\n });\r\n },\r\n};\r\n","import { registerGame, listGames } from \"./index.js\";\r\nimport type { Game } from \"./index.js\";\r\nimport brickBreaker from \"./brick-breaker/index.js\";\r\nimport coderCheck from \"./coder-check/index.js\";\r\n\r\n/** 在此注册所有游戏 */\r\nexport function initGames(): Game[] {\r\n registerGame(brickBreaker);\r\n registerGame(coderCheck);\r\n return listGames();\r\n}\r\n","/** dskcode 退出码规范 */\r\nexport const ExitCode = {\r\n /** 正常执行完成 */\r\n SUCCESS: 0,\r\n /** 通用错误 */\r\n GENERAL_ERROR: 1,\r\n /** 配置错误 */\r\n CONFIG_ERROR: 2,\r\n /** 用户通过 Ctrl+C 中断 */\r\n SIGINT: 130,\r\n} as const;\r\n","#!/usr/bin/env node\r\n\r\nimport { createCli } from \"./cli/index.js\";\r\nimport { ExitCode } from \"./cli/exit-codes.js\";\r\n\r\nprocess.on(\"SIGINT\", () => {\r\n process.exit(ExitCode.SIGINT);\r\n});\r\n\r\nconst program = createCli();\r\n\r\ntry {\r\n await program.parseAsync(process.argv);\r\n} catch (err: unknown) {\r\n const error = err as { exitCode?: number; code?: string };\r\n\r\n if (error.code === \"commander.helpDisplayed\" || error.code === \"commander.version\") {\r\n process.exit(error.exitCode ?? ExitCode.SUCCESS);\r\n }\r\n\r\n if (typeof error.exitCode === \"number\") {\r\n process.exit(error.exitCode);\r\n }\r\n\r\n console.error(String(err));\r\n process.exit(ExitCode.GENERAL_ERROR);\r\n}\r\n"],"mappings":";;;;;;AAAA,SAAS,eAAe;;;ACgBxB,eAAsB,uBAA6D;AACjF,QAAM,OAAO,KAAK,gBAAgB;AAClC,QAAM,UAAU,KAAK,WAAW;AAEhC,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,WAAW,KAAK,MAAM;AAAA,EACvC,QAAQ;AACN,UAAM,EAAE,cAAc,IAAI,MAAM,OAAO,sBAAoB;AAC3D,aAAS;AAAA,EACX;AAEA,SAAO,EAAE,QAAQ,QAAQ;AAC3B;;;AC5BA,OAAO,WAAW;AAEX,SAAS,WAAWA,UAA0B;AACnD,QAAM,QAAkB,CAAC;AAEzB,QAAM,KAAK,EAAE;AACb,QAAM,KAAK,MAAM,KAAK,eAAK,CAAC;AAC5B,QAAM,KAAK,KAAK,MAAM,KAAK,SAAS,CAAC,IAAI,MAAM,IAAI,kBAAkB,CAAC,IAAI,MAAM,MAAM,WAAW,CAAC,IAAI,MAAM,IAAI,WAAW,CAAC,EAAE;AAC9H,QAAM,KAAK,EAAE;AAEb,QAAM,aAAaA,SAAQ,QAAQ;AAAA,IACjC,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,SAAS,eAAe,EAAE,SAAS;AAAA,EACrE;AACA,MAAI,WAAW,SAAS,GAAG;AACzB,UAAM,KAAK,MAAM,KAAK,2BAAO,CAAC;AAC9B,eAAW,OAAO,YAAY;AAC5B,YAAM,QAAQ,CAAC,IAAI,OAAO,IAAI,IAAI,EAAE,OAAO,OAAO,EAAE,KAAK,IAAI;AAC7D,YAAM,KAAK,KAAK,MAAM,KAAK,MAAM,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,eAAe,EAAE,EAAE;AAAA,IACzE;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,MAAM,KAAK,2BAAO,CAAC;AAC9B,aAAW,QAAQ,CAAC,cAAc,eAAe,GAAG;AAClD,UAAM,MAAMA,SAAQ,QAAQ;AAAA,MAC1B,CAAC,MAAM,EAAE,UAAU,KAAK,SAAS,MAAM,IAAI,WAAW;AAAA,IACxD;AACA,QAAI,KAAK;AACP,YAAM,KAAK,KAAK,MAAM,KAAK,KAAK,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,eAAe,EAAE,EAAE;AAAA,IACxE;AAAA,EACF;AACA,QAAM,KAAK,EAAE;AAEb,QAAM,OAAOA,SAAQ,SAAS,OAAO,CAAC,MAAM,CAAC,EAAE,KAAK,EAAE,WAAW,MAAM,CAAC;AACxE,MAAI,KAAK,SAAS,GAAG;AACnB,UAAM,KAAK,MAAM,KAAK,eAAK,CAAC;AAC5B,eAAW,OAAO,MAAM;AACtB,YAAM,KAAK,KAAK,MAAM,MAAM,IAAI,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,IAAI,YAAY,CAAC,EAAE;AAAA,IAC3E;AACA,UAAM,KAAK,EAAE;AAAA,EACf;AAEA,QAAM,KAAK,MAAM,KAAK,eAAK,CAAC;AAC5B,QAAM,KAAK,KAAK,MAAM,IAAI,8CAAW,CAAC,EAAE;AACxC,QAAM,KAAK,gBAAgB;AAC3B,QAAM,KAAK,KAAK,MAAM,IAAI,kDAAe,CAAC,EAAE;AAC5C,QAAM,KAAK,0DAA4B;AACvC,QAAM,KAAK,KAAK,MAAM,IAAI,wCAAU,CAAC,EAAE;AACvC,QAAM,KAAK,iBAAiB;AAC5B,QAAM,KAAK,KAAK,MAAM,IAAI,+CAAiB,CAAC,EAAE;AAC9C,QAAM,KAAK,sBAAsB;AACjC,QAAM,KAAK,EAAE;AAEb,SAAO,MAAM,KAAK,IAAI;AACxB;;;ACvDA,SAAS,cAAc;AAShB,SAAS,UAAU,MAAoC;AAC5D,QAAM,EAAE,eAAe,OAAO,QAAQ,IAAI,OAAO,IAAI;AACrD,SAAO,EAAE,eAAe,cAAc,GAAG,OAAO,QAAQ;AAC1D;;;ACZA,SAAS,YAAY;AACrB,OAAO,gBAAgB;AAWf,cAEO,YAFP;;;ACZR,SAAS,KAAK,QAAAC,aAAY;AAqBpB,iBAAAC,aAAA;;;ACrBN,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAC1B,SAAS,WAAW,gBAAgB;AA6BxB,gBAAAC,YAAA;;;AC9BZ,SAAS,OAAAC,MAAK,QAAAC,aAAY;AAC1B,OAAO,eAAe;AACtB,SAAS,aAAAC,YAAW,YAAAC,WAAU,mBAAmB;AA4GjC,gBAAAC,MAUN,QAAAC,aAVM;AA1GhB,IAAM,gBAAgB,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AAE5E,IAAM,aAAa;AAAA,EACjB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAEA,IAAM,WAAoE;AAAA,EACxE,SAAS,EAAE,MAAM,4BAAQ,SAAS,MAAM,GAAG;AAAA,EAC3C,SAAS,EAAE,MAAM,4BAAQ,SAAS,MAAM,GAAG;AAAA,EAC3C,SAAS;AAAA,IACP,MAAM;AAAA,IACN,SAAS,MACP;AAAA,MACE;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,IACF,EAAE,KAAK,IAAI;AAAA,EACf;AAAA,EACA,UAAU,EAAE,MAAM,wCAAU,SAAS,MAAM,GAAG;AAAA,EAC9C,YAAY,EAAE,MAAM,wCAAU,SAAS,MAAM,iBAAiB;AAChE;AAaO,SAAS,YAAY,EAAE,eAAe,WAAW,QAAQ,GAAqB;AACnF,QAAM,CAAC,QAAQ,SAAS,IAAIF,UAAS,CAAC;AACtC,QAAM,CAAC,UAAU,WAAW,IAAIA,UAAwB,CAAC,CAAC;AAC1D,QAAM,CAAC,OAAO,QAAQ,IAAIA,UAAS,EAAE;AAErC,EAAAD,WAAU,MAAM;AACd,UAAM,QAAQ,YAAY,MAAM;AAC9B,gBAAU,CAAC,UAAU,OAAO,KAAK,cAAc,MAAM;AAAA,IACvD,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,CAAC;AAEL,QAAM,eAAe,YAAY,CAAC,UAAkB;AAClD,UAAM,UAAU,MAAM,KAAK;AAC3B,QAAI,CAAC,QAAS;AAEd,QAAI,QAAQ,WAAW,GAAG,GAAG;AAC3B,YAAM,MAAM,SAAS,QAAQ,YAAY,CAAC;AAC1C,UAAI,KAAK;AACP,YAAI,QAAQ,YAAY,MAAM,WAAW,QAAQ,YAAY,MAAM,SAAS;AAC1E,kBAAQ,KAAK,CAAC;AACd;AAAA,QACF;AACA,YAAI,QAAQ,YAAY,MAAM,UAAU;AACtC,sBAAY,CAAC,CAAC;AACd,mBAAS,EAAE;AACX;AAAA,QACF;AACA,cAAM,SAAS,IAAI,QAAQ;AAC3B,YAAI,QAAQ;AACV,sBAAY,CAAC,SAAS;AAAA,YACpB,GAAG;AAAA,YACH,EAAE,MAAM,QAAQ,SAAS,QAAQ;AAAA,YACjC,EAAE,MAAM,aAAa,SAAS,OAAO;AAAA,UACvC,CAAC;AAAA,QACH;AACA,iBAAS,EAAE;AACX;AAAA,MACF;AACA,kBAAY,CAAC,SAAS;AAAA,QACpB,GAAG;AAAA,QACH,EAAE,MAAM,QAAQ,SAAS,QAAQ;AAAA,QACjC,EAAE,MAAM,aAAa,SAAS,iCAAQ,OAAO,8CAAgB;AAAA,MAC/D,CAAC;AACD,eAAS,EAAE;AACX;AAAA,IACF;AAEA,gBAAY,CAAC,SAAS;AAAA,MACpB,GAAG;AAAA,MACH,EAAE,MAAM,QAAQ,SAAS,QAAQ;AAAA,MACjC,EAAE,MAAM,aAAa,SAAS,wIAAyC;AAAA,IACzE,CAAC;AACD,aAAS,EAAE;AAAA,EACb,GAAG,CAAC,CAAC;AAEL,SACE,gBAAAG,MAACL,MAAA,EAAI,eAAc,UAAS,aAAa,GAAG,cAAc,GAExD;AAAA,oBAAAK,MAACL,MAAA,EAAI,eAAc,OAAM,cAAc,GAErC;AAAA,sBAAAI,KAACJ,MAAA,EAAI,eAAc,UAAS,aAAa,GACtC,qBAAW,IAAI,CAAC,MAAM,MAAM;AAC3B,cAAM,cAAc,IAAI,UAAU,cAAc;AAChD,eACE,gBAAAI,KAACJ,MAAA,EACC,0BAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAO,cAAc,UAAU,GACvC,gBACH,KAHQ,CAIV;AAAA,MAEJ,CAAC,GACH;AAAA,MAGA,gBAAAI,MAACL,MAAA,EAAI,eAAc,UAAS,gBAAe,UACzC;AAAA,wBAAAK,MAACJ,OAAA,EAAK,OAAM,WAAW;AAAA;AAAA,UAAO;AAAA,UAAK;AAAA,UAAc;AAAA,WAAW;AAAA,QAC5D,gBAAAI,MAACJ,OAAA,EAAK,OAAM,WAAW;AAAA;AAAA,UAAO;AAAA,UAAK;AAAA,UAAU;AAAA,WAAI;AAAA,QAChD,UAAU,gBAAAG,KAACH,OAAA,EAAK,OAAM,WAAW,8BAAc,IAAU;AAAA,SAC5D;AAAA,OACF;AAAA,IAGA,gBAAAG,KAACJ,MAAA,EAAI,eAAc,UAAS,WAAW,GACpC,mBAAS,IAAI,CAAC,KAAK,MAClB,gBAAAK,MAACL,MAAA,EAAY,WAAW,GACtB;AAAA,sBAAAI,KAACJ,MAAA,EAAI,OAAO,GAAG,YAAY,GACzB,0BAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAO,IAAI,SAAS,SAAS,YAAY,WACjD,cAAI,SAAS,SAAS,gBAAS,eAClC,GACF;AAAA,MACA,gBAAAG,KAACJ,MAAA,EAAI,UAAU,GACb,0BAAAI,KAACH,OAAA,EAAK,MAAK,QAAQ,cAAI,SAAQ,GACjC;AAAA,SARQ,CASV,CACD,GACH;AAAA,IAGA,gBAAAI,MAACL,MAAA,EAAI,WAAW,GACd;AAAA,sBAAAI,KAACJ,MAAA,EAAI,OAAO,GAAG,YAAY,GACzB,0BAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAM,WACd,sBACH,GACF;AAAA,MACA,gBAAAG,KAACJ,MAAA,EAAI,UAAU,GACb,0BAAAI;AAAA,QAAC;AAAA;AAAA,UACC,OAAO;AAAA,UACP,UAAU;AAAA,UACV,UAAU;AAAA,UACV,aAAY;AAAA;AAAA,MACd,GACF;AAAA,OACF;AAAA,IAEA,gBAAAA,KAACJ,MAAA,EAAI,WAAW,GACd,0BAAAI,KAACH,OAAA,EAAK,OAAM,WAAU,UAAQ,MAC3B,iBAAO,SAAI,OAAO,EAAE,GACvB,GACF;AAAA,KACF;AAEJ;;;ACtKA,SAAS,OAAAK,MAAK,QAAAC,OAAM,gBAAgB;AACpC,SAAS,YAAAC,WAAU,eAAAC,oBAAmB;AAkC9B,gBAAAC,MASI,QAAAC,aATJ;AAzBD,SAAS,WAAW,EAAE,OAAO,UAAU,OAAO,GAAoB;AACvE,QAAM,CAAC,eAAe,gBAAgB,IAAIH,UAAS,CAAC;AAEpD;AAAA,IACEC;AAAA,MACE,CAAC,OAAO,QAAQ;AACd,YAAI,MAAM,WAAW,EAAG;AACxB,YAAI,IAAI,WAAW,UAAU,KAAK;AAChC,2BAAiB,CAAC,SAAU,OAAO,IAAI,OAAO,IAAI,MAAM,SAAS,CAAE;AAAA,QACrE,WAAW,IAAI,aAAa,UAAU,KAAK;AACzC,2BAAiB,CAAC,SAAU,OAAO,MAAM,SAAS,IAAI,OAAO,IAAI,CAAE;AAAA,QACrE,WAAW,IAAI,QAAQ;AACrB,gBAAM,OAAO,MAAM,aAAa;AAChC,cAAI,KAAM,UAAS,IAAI;AAAA,QACzB,WAAW,IAAI,UAAU,UAAU,KAAK;AACtC,iBAAO;AAAA,QACT;AAAA,MACF;AAAA,MACA,CAAC,OAAO,eAAe,UAAU,MAAM;AAAA,IACzC;AAAA,EACF;AAEA,SACE,gBAAAE,MAACL,MAAA,EAAI,eAAc,UACjB;AAAA,oBAAAI,KAACJ,MAAA,EAAI,cAAc,GACjB,0BAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAM,WAAU,gDAE3B,GACF;AAAA,IAEA,gBAAAG,KAACJ,MAAA,EAAI,eAAc,UAChB,gBAAM,IAAI,CAAC,MAAM,UAAU;AAC1B,YAAM,aAAa,UAAU;AAC7B,aACE,gBAAAK,MAACL,MAAA,EAAkB,eAAc,OAC/B;AAAA,wBAAAI,KAACJ,MAAA,EAAI,OAAO,GAAG,YAAY,GACxB,uBACC,gBAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAM,WACd,qBACH,IAEA,gBAAAG,KAACH,OAAA,EAAM,gBAAK,GAEhB;AAAA,QACA,gBAAAG,KAACJ,MAAA,EAAI,OAAO,IAAI,YAAY,GAC1B,0BAAAI,KAACH,OAAA,EAAK,MAAI,MAAC,OAAO,aAAa,YAAY,WACxC,eAAK,MACR,GACF;AAAA,QACA,gBAAAG,KAACJ,MAAA,EACC,0BAAAI,KAACH,OAAA,EAAK,OAAM,WAAW,eAAK,aAAY,GAC1C;AAAA,WAjBQ,KAAK,EAkBf;AAAA,IAEJ,CAAC,GACH;AAAA,IAEA,gBAAAG,KAACJ,MAAA,EAAI,WAAW,GACd,0BAAAI,KAACH,OAAA,EAAK,UAAQ,MACX,8EACH,GACF;AAAA,KACF;AAEJ;;;AC/DA,IAAM,WAAW,oBAAI,IAAkB;AAEhC,SAAS,aAAa,MAAkB;AAC7C,WAAS,IAAI,KAAK,IAAI,IAAI;AAC5B;AAEO,SAAS,QAAQ,IAA8B;AACpD,SAAO,SAAS,IAAI,EAAE;AACxB;AAEO,SAAS,YAAoB;AAClC,SAAO,MAAM,KAAK,SAAS,OAAO,CAAC;AACrC;;;ACvBA,SAAS,OAAAK,MAAK,QAAAC,OAAM,YAAAC,WAAU,UAAAC,eAAc;AAC5C,SAAS,YAAAC,WAAU,aAAAC,YAAW,QAAQ,eAAAC,oBAAmB;AAiR/C,SACgB,OAAAC,MADhB,QAAAC,aAAA;AA/QV,IAAM,aAAa;AACnB,IAAM,cAAc;AACpB,IAAM,eAAe;AACrB,IAAM,eAAe,CAAC,KAAK,KAAK,IAAI,EAAE;AAyBtC,IAAM,SAAqB;AAAA,EACzB,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,uBAAgB,SAAS,MAAM,KAAK;AAAA,EACrE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,yBAAgB,SAAS,MAAM,KAAK;AAAA,EACrE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,yBAAgB,SAAS,MAAM,KAAK;AAAA,EACrE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,sBAAiB,SAAS,CAAC,GAAG,OAAO,IAAI,KAAK,MAAM,EAAE;AAAA,EACvF,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,sBAAiB,SAAS,CAAC,GAAG,GAAG,GAAG,OAAO,KAAK,KAAK,IAAI,KAAK,EAAE;AAAA,EACjG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,4BAAgB,SAAS,CAAC,GAAG,MAAM,IAAI,MAAM,KAAM,KAAK,KAAK,KAAK,EAAG;AAAA,EACtG,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,4BAAgB,SAAS,CAAC,GAAG,GAAG,IAAI,OAAO,MAAM,KAAK,MAAM,KAAK,KAAK,MAAM,KAAK,MAAM,KAAK,EAAE;AAAA,EAC/H,EAAE,MAAM,GAAG,MAAM,IAAI,IAAI,GAAG,MAAM,0BAAgB,SAAS,MAAM,KAAK;AAAA,EACtE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,yBAAgB,SAAS,MAAM,KAAK;AAAA,EACrE,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,GAAG,MAAM,yBAAgB,SAAS,MAAM,KAAK;AACvE;AAEA,SAAS,SAAS,OAAyB;AACzC,SAAO,QAAQ,QAAQ,KAAK,OAAO,MAAM;AAC3C;AAEA,SAAS,aAAa,OAAwB;AAC5C,QAAM,MAAM,SAAS,KAAK;AAC1B,QAAM,SAAkB,CAAC;AACzB,QAAM,MAAM;AACZ,QAAM,SAAS,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,KAAK;AACpD,QAAM,SAAS,KAAK,OAAO,aAAa,UAAU,CAAC;AACnD,QAAM,OAAO,IAAI,KAAK;AAEtB,WAAS,MAAM,GAAG,MAAM,IAAI,MAAM,OAAO;AACvC,aAAS,MAAM,GAAG,MAAM,IAAI,MAAM,OAAO;AACvC,UAAI,IAAI,QAAQ,KAAK,KAAK,IAAI,MAAM,IAAI,IAAI,GAAG;AAC7C,eAAO,KAAK;AAAA,UACV,GAAG,SAAS,MAAM;AAAA,UAClB,GAAG,IAAI,MAAM;AAAA,UACb,GAAG,IAAI;AAAA,UACP,OAAO;AAAA,QACT,CAAC;AAAA,MACH;AAAA,IACF;AAAA,EACF;AACA,SAAO;AACT;AAiBA,SAAS,mBAAmB,OAA0B;AACpD,QAAM,MAAM,SAAS,KAAK;AAC1B,QAAM,SAAS,IAAI,OAAO,IAAI,MAAM,IAAI,OAAO,KAAK;AACpD,QAAM,SAAS,KAAK,OAAO,aAAa,UAAU,CAAC;AACnD,SAAO;AAAA,IACL;AAAA,IACA,QAAQ,aAAa,KAAK;AAAA,IAC1B,SAAS,KAAK,MAAM,aAAa,CAAC,IAAI,KAAK,MAAM,eAAe,CAAC;AAAA,IACjE,MAAM,EAAE,GAAG,aAAa,GAAG,GAAG,cAAc,EAAE;AAAA,IAC9C,SAAS,EAAE,GAAG,GAAG,GAAG,GAAG;AAAA,IACvB,OAAO;AAAA,IACP,OAAO;AAAA,IACP,UAAU;AAAA,IACV,KAAK;AAAA,IACL,QAAQ;AAAA,EACV;AACF;AAIA,SAAS,OAAO,OAAwB;AACtC,MAAI,MAAM,UAAU,MAAM,YAAY,MAAM,IAAK;AAEjD,QAAM,KAAK,KAAK,MAAM,QAAQ;AAC9B,QAAM,KAAK,KAAK,MAAM,QAAQ;AAE9B,MAAI,MAAM,KAAK,KAAK,GAAG;AAAE,UAAM,KAAK,IAAI;AAAG,UAAM,QAAQ,IAAI;AAAA,EAAG;AAChE,MAAI,MAAM,KAAK,KAAK,aAAa,GAAG;AAAE,UAAM,KAAK,IAAI,aAAa;AAAG,UAAM,QAAQ,IAAI;AAAA,EAAI;AAC3F,MAAI,MAAM,KAAK,KAAK,GAAG;AAAE,UAAM,KAAK,IAAI;AAAG,UAAM,QAAQ,IAAI;AAAA,EAAG;AAGhE,MACE,MAAM,KAAK,MAAM,cAAc,KAC/B,MAAM,KAAK,KAAK,MAAM,WACtB,MAAM,KAAK,KAAK,MAAM,UAAU,cAChC;AACA,UAAM,QAAQ,IAAI;AAClB,UAAM,UAAU,MAAM,KAAK,IAAI,MAAM,WAAW;AAChD,UAAM,QAAQ,IAAI,SAAS,MAAM,KAAK;AAAA,EACxC;AAGA,MAAI,MAAM,KAAK,IAAI,aAAa;AAC9B,UAAM;AACN,QAAI,MAAM,SAAS,GAAG;AACpB,YAAM,WAAW;AAAA,IACnB,OAAO;AACL,YAAM,OAAO,EAAE,GAAG,aAAa,GAAG,GAAG,cAAc,EAAE;AACrD,YAAM,UAAU,EAAE,GAAG,GAAG,GAAG,GAAG;AAC9B,YAAM,UAAU,KAAK,MAAM,aAAa,CAAC,IAAI,KAAK,MAAM,eAAe,CAAC;AAAA,IAC1E;AAAA,EACF;AAGA,QAAM,WAAW,MAAM,OAAO,KAAK,CAAC,MAAM;AACxC,QAAI,CAAC,EAAE,MAAO,QAAO;AACrB,WAAO,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE,IAAI,EAAE,KAAK,MAAM,KAAK,KAAK,EAAE,KAAK,MAAM,KAAK,IAAI,EAAE,IAAI;AAAA,EACxG,CAAC;AAED,MAAI,UAAU;AACZ,aAAS,QAAQ;AACjB,UAAM,SAAS;AACf,UAAM,QAAQ,IAAI,CAAC,MAAM,QAAQ;AAAA,EACnC;AAEA,MAAI,MAAM,OAAO,MAAM,CAAC,MAAM,CAAC,EAAE,KAAK,EAAG,OAAM,MAAM;AACvD;AAIA,SAAS,WAAW,OAA0B;AAC5C,QAAM,QAAkB,CAAC;AAEzB,WAAS,gBAAgB,GAAW,GAA+B;AACjE,UAAM,MAAM,KAAK,OAAO,IAAI,KAAK,CAAC;AAClC,QAAI,OAAO,GAAG;AACZ,YAAM,IAAI,MAAM,OAAO,KAAK,CAAC,OAAO,GAAG,MAAM,KAAK,GAAG,SAAS,KAAK,GAAG,KAAK,IAAI,GAAG,IAAI,GAAG,CAAC;AAC1F,UAAI,EAAG,QAAO,MAAM,aAAa;AAAA,IACnC;AACA,WAAO;AAAA,EACT;AAEA,WAAS,IAAI,GAAG,IAAI,aAAa,KAAK;AACpC,QAAI,OAAO;AACX,aAAS,IAAI,GAAG,IAAI,YAAY,KAAK;AACnC,YAAM,SAAS,MAAM,KAAK,MAAM,KAAK,MAAM,KAAK,MAAM;AACtD,YAAM,WAAW,MAAM,cAAc,KAAK,KAAK,MAAM,WAAW,IAAI,MAAM,UAAU;AACpF,YAAM,WAAW,gBAAgB,GAAG,CAAC;AAErC,UAAI,QAAQ;AACV,gBAAQ;AAAA,MACV,WAAW,UAAU;AACnB,gBAAQ;AAAA,MACV,WAAW,aAAa,QAAW;AACjC,gBAAQ,aAAa,aAAa,QAAQ,CAAW;AAAA,MACvD,OAAO;AACL,gBAAQ;AAAA,MACV;AAAA,IACF;AACA,UAAM,KAAK,IAAI;AAAA,EACjB;AAEA,SAAO,MAAM,IAAI,CAAC,MAAM,SAAI,CAAC,QAAG,EAAE,KAAK,IAAI;AAC7C;AAQA,SAAS,iBAAiB,EAAE,QAAQ,QAAQ,GAA0B;AACpE,QAAM,CAAC,cAAc,eAAe,IAAIJ,UAAS,CAAC;AAClD,QAAM,CAAC,gBAAgB,iBAAiB,IAAIA,UAAS,IAAI;AACzD,QAAM,WAAW,OAAkB,mBAAmB,YAAY,CAAC;AACnE,QAAM,CAAC,MAAM,OAAO,IAAIA,UAAS,CAAC;AAClC,QAAM,YAAY,OAAO,OAAO;AAChC,YAAU,UAAU;AAEpB,EAAAC,WAAU,MAAM;AACd,QAAI,eAAgB;AACpB,UAAM,WAAW,YAAY,MAAM;AACjC,aAAO,SAAS,OAAO;AACvB,cAAQ,CAAC,MAAM,IAAI,CAAC;AAAA,IACtB,GAAG,EAAE;AACL,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,cAAc,CAAC;AAGnB,QAAM,UAAUC,aAAY,CAAC,UAAmB;AAC9C,UAAM,KAAK,SAAS,SAAS,QAAQ;AACrC,aAAS,UAAU,mBAAmB,EAAE;AACxC,oBAAgB,EAAE;AAClB,sBAAkB,KAAK;AACvB,YAAQ,CAAC;AAAA,EACX,GAAG,CAAC,CAAC;AAGL,QAAM,mBAAmBA,aAAY,MAAM;AACzC,sBAAkB,IAAI;AAAA,EACxB,GAAG,CAAC,CAAC;AAEL,EAAAJ;AAAA,IACEI,aAAY,CAAC,OAAO,QAAQ;AAC1B,YAAMG,KAAI,SAAS;AAGnB,UAAI,gBAAgB;AAClB,YAAI,SAAS,OAAO,SAAS,KAAK;AAChC,kBAAQ,OAAO,KAAK,CAAC;AAAA,QACvB,WAAW,UAAU,KAAK;AACxB,kBAAQ,EAAE;AAAA,QACZ,WAAW,IAAI,UAAU,UAAU,KAAK;AACtC,oBAAU,QAAQ;AAAA,QACpB;AACA;AAAA,MACF;AAEA,UAAI,IAAI,WAAW;AACjB,QAAAA,GAAE,UAAU,KAAK,IAAI,GAAGA,GAAE,UAAU,CAAC;AACrC,gBAAQ,CAAC,MAAM,IAAI,CAAC;AAAA,MACtB,WAAW,IAAI,YAAY;AACzB,QAAAA,GAAE,UAAU,KAAK,IAAI,aAAa,cAAcA,GAAE,UAAU,CAAC;AAC7D,gBAAQ,CAAC,MAAM,IAAI,CAAC;AAAA,MACtB,WAAW,UAAU,OAAO,UAAU,KAAK;AACzC,QAAAA,GAAE,SAAS,CAACA,GAAE;AAAA,MAChB,WAAW,UAAU,KAAK;AACxB,YAAIA,GAAE,YAAYA,GAAE,IAAK,SAAQ;AAAA,MACnC,WAAW,UAAU,KAAK;AACxB,YAAIA,GAAE,YAAYA,GAAE,IAAK,kBAAiB;AAAA,MAC5C,WAAW,UAAU,OAAO,IAAI,QAAQ;AACtC,kBAAU,QAAQ;AAAA,MACpB;AAAA,IACF,GAAG,CAAC,gBAAgB,SAAS,gBAAgB,CAAC;AAAA,EAChD;AAEA,QAAM,IAAI,SAAS;AACnB,QAAM,aAAa,EAAE,OAAO,OAAO,CAAC,MAAM,EAAE,KAAK,EAAE;AACnD,QAAM,QAAQ,WAAW,CAAC;AAC1B,QAAM,MAAM,SAAS,EAAE,KAAK;AAE5B,OAAK;AAEL,SACE,gBAAAD,MAACR,MAAA,EAAI,eAAc,UAEjB;AAAA,oBAAAQ,MAACR,MAAA,EAAI,eAAc,OACjB;AAAA,sBAAAO,KAACP,MAAA,EAAI,OAAO,IACV,0BAAAQ,MAACP,OAAA,EAAK;AAAA;AAAA,QACA,EAAE;AAAA,QAAM;AAAA,QAAE,gBAAAM,KAACN,OAAA,EAAK,OAAM,QAAQ,cAAI,MAAK;AAAA,SAC7C,GACF;AAAA,MACA,gBAAAM,KAACP,MAAA,EAAI,OAAO,IACV,0BAAAQ,MAACP,OAAA,EAAK;AAAA;AAAA,QACA,gBAAAM,KAACN,OAAA,EAAK,OAAM,UAAU,iBAAO,EAAE,KAAK,EAAE,SAAS,GAAG,GAAG,GAAE;AAAA,SAC7D,GACF;AAAA,MACA,gBAAAM,KAACP,MAAA,EAAI,OAAO,IACV,0BAAAQ,MAACP,OAAA,EAAK;AAAA;AAAA,QACA,gBAAAM,KAACN,OAAA,EAAK,OAAM,OAAO,mBAAI,OAAO,KAAK,IAAI,GAAG,EAAE,KAAK,CAAC,GAAE;AAAA,SAC1D,GACF;AAAA,MACA,gBAAAM,KAACP,MAAA,EAAI,OAAO,IACV,0BAAAQ,MAACP,OAAA,EAAK;AAAA;AAAA,QACA,gBAAAM,KAACN,OAAA,EAAK,OAAM,QAAQ,sBAAW;AAAA,SACrC,GACF;AAAA,MACA,gBAAAM,KAACP,MAAA,EACC,0BAAAQ,MAACP,OAAA,EAAK,OAAO,EAAE,SAAS,SAAS,SAAS;AAAA;AAAA,QACtC,EAAE,SAAS,iBAAO;AAAA,QAAM;AAAA,SAC5B,GACF;AAAA,OACF;AAAA,IAGA,gBAAAO,MAACR,MAAA,EAAI,eAAc,UACjB;AAAA,sBAAAQ,MAACP,OAAA,EAAK;AAAA;AAAA,QAAE,SAAI,OAAO,UAAU;AAAA,QAAE;AAAA,SAAC;AAAA,MAChC,gBAAAM,KAACN,OAAA,EAAM,2BAAiB,mEAAgC,OAAM;AAAA,MAC9D,gBAAAO,MAACP,OAAA,EAAK;AAAA;AAAA,QAAE,SAAI,OAAO,UAAU;AAAA,QAAE;AAAA,SAAC;AAAA,OAClC;AAAA,IAGC,kBACC,gBAAAO,MAACR,MAAA,EAAI,WAAW,GAAG,eAAc,UAC/B;AAAA,sBAAAO,KAACN,OAAA,EAAK,MAAI,MAAC,OAAM,UAAS,sCAAI;AAAA,MAC9B,gBAAAM,KAACP,MAAA,EAAI,eAAc,OAAM,UAAS,QAC/B,iBAAO,IAAI,CAAC,IAAI,MACf,gBAAAO,KAACP,MAAA,EAAY,OAAO,IAClB,0BAAAQ,MAACP,OAAA,EACC;AAAA,wBAAAM,KAACN,OAAA,EAAK,OAAO,iBAAiB,IAAI,IAAI,UAAU,SAC7C,cAAI,MAAM,KAAK,MAAM,OAAO,IAAI,CAAC,GACpC;AAAA,QAAO;AAAA,QACJ,GAAG;AAAA,QAAK;AAAA,QAAG,GAAG;AAAA,QAAK;AAAA,QAAE,GAAG;AAAA,QAAK;AAAA,SAClC,KANQ,CAOV,CACD,GACH;AAAA,MACA,gBAAAM,KAACP,MAAA,EAAI,WAAW,GACd,0BAAAO,KAACN,OAAA,EAAK,UAAQ,MAAC,4DAAW,GAC5B;AAAA,OACF;AAAA,IAID,CAAC,mBAAmB,EAAE,YAAY,EAAE,QACnC,gBAAAO,MAACR,MAAA,EAAI,WAAW,GACd;AAAA,sBAAAO,KAACN,OAAA,EAAK,MAAI,MAAC,OAAO,EAAE,WAAW,QAAQ,SACpC,YAAE,WAAW,mCAAU,kCAC1B;AAAA,MACA,gBAAAO,MAACP,OAAA,EACE;AAAA;AAAA,QAAS,gBAAAM,KAACN,OAAA,EAAK,OAAM,UAAU,YAAE,OAAM;AAAA,SAC1C;AAAA,OACF;AAAA,IAID,CAAC,kBACA,gBAAAM,KAACP,MAAA,EAAI,WAAW,GACb,YAAE,YAAY,EAAE,MACf,gBAAAO,KAACN,OAAA,EAAK,UAAQ,MACX,wFACH,IAEA,gBAAAM,KAACN,OAAA,EAAK,UAAQ,MACX,wEACH,GAEJ;AAAA,KAEJ;AAEJ;AAIA,IAAO,wBAAQ;AAAA,EACb,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,YAAY;AAChB,UAAM,IAAI,QAAc,CAAC,YAAY;AACnC,YAAM,EAAE,QAAQ,IAAIE;AAAA,QAClB,gBAAAI,KAAC,oBAAiB,QAAQ,MAAM;AAAE,kBAAQ;AAAG,kBAAQ;AAAA,QAAG,GAAG;AAAA,MAC7D;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;ACpXA,SAAS,OAAAG,MAAK,QAAAC,OAAM,YAAAC,WAAU,UAAAC,eAAc;AAC5C,SAAS,YAAAC,WAAU,aAAAC,YAAW,UAAAC,SAAQ,eAAAC,oBAAmB;AAyY5C,gBAAAC,MACM,QAAAC,aADN;AAvYb,IAAM,SAAS;AACf,IAAM,SAAS;AACf,IAAM,UAAU;AAEhB,IAAM,YAAY;AAClB,IAAMC,iBAAgB,CAAC,WAAW,WAAW,WAAW,WAAW,SAAS;AAG5E,IAAM,YAAsC;AAAA,EAC1C,KAAK,CAAC,0CAAY,gCAAY,gCAAY,gCAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,sBAAY,gCAAY,sBAAY,sBAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,sBAAY,0CAAY,sBAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,sBAAY,0CAAY,sBAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,gCAAY,gCAAY,0CAAY,sBAAY,oBAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,sBAAY,0CAAY,sBAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,sBAAY,0CAAY,gCAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,sBAAY,sBAAY,sBAAY,oBAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,gCAAY,0CAAY,gCAAY,wCAAU;AAAA,EAChE,KAAK,CAAC,0CAAY,gCAAY,0CAAY,sBAAY,wCAAU;AAClE;AAEA,SAAS,gBAAgB,UAA4B;AACnD,QAAM,QAAQ,CAAC,IAAI,IAAI,IAAI,IAAI,EAAE;AACjC,aAAW,MAAM,UAAU;AACzB,UAAM,MAAM,UAAU,EAAE,KAAK,UAAU,GAAG;AAC1C,aAAS,IAAI,GAAG,IAAI,GAAG,KAAK;AAC1B,YAAM,CAAC,KAAK,OAAO,IAAI,CAAC,KAAK;AAAA,IAC/B;AAAA,EACF;AAEA,QAAM,MAAM;AACZ,SAAO,MAAM,IAAI,CAAC,MAAM,IAAI,OAAO,GAAG,IAAI,CAAC;AAC7C;AAEA,SAAS,SAAS,KAAqB;AACrC,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,QAAM,IAAI,SAAS,IAAI,MAAM,GAAG,CAAC,GAAG,EAAE;AACtC,SAAO,GAAG,CAAC,IAAI,CAAC,IAAI,CAAC;AACvB;AAIA,IAAM,aAAa;AAAA;AAAA,EAEjB;AAAA,EAAS;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAW;AAAA,EAAU;AAAA,EAC9D;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAU;AAAA,EAAY;AAAA,EAAY;AAAA,EAC9D;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAW;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EACrD;AAAA,EAAU;AAAA,EAAU;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAU;AAAA;AAAA,EAGzD;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EAAO;AAAA,EACzD;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAc;AAAA,EAAa;AAAA,EAAU;AAAA,EAClE;AAAA,EAAY;AAAA,EAAU;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAS;AAAA,EAClD;AAAA,EAAc;AAAA,EAAW;AAAA,EAAQ;AAAA,EAAa;AAAA;AAAA,EAG9C;AAAA,EAAO;AAAA,EAAS;AAAA,EAAc;AAAA,EAAc;AAAA,EAAW;AAAA,EACvD;AAAA,EAAO;AAAA,EAAU;AAAA,EAAU;AAAA,EAAa;AAAA,EAAU;AAAA,EAClD;AAAA,EAAQ;AAAA,EAAO;AAAA,EAAS;AAAA,EAAW;AAAA,EAAU;AAAA,EAAS;AAAA,EACtD;AAAA,EAAS;AAAA,EAAS;AAAA,EAAM;AAAA,EAAU;AAAA,EAAS;AAAA;AAAA,EAG3C;AAAA,EAAO;AAAA,EAAS;AAAA,EAAM;AAAA,EAAU;AAAA,EAAS;AAAA,EAAS;AAAA,EAClD;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA,EACrD;AAAA,EAAS;AAAA,EAAU;AAAA,EAAS;AAAA,EAAU;AAAA,EAAU;AAAA,EAAU;AAAA;AAAA,EAG1D;AAAA,EAAU;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAQ;AAAA,EACrD;AAAA,EAAM;AAAA,EAAM;AAAA,EAAU;AAAA,EAAY;AAAA,EAAW;AAAA,EAAS;AAAA,EACtD;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAS;AAAA,EAAU;AAAA,EAAU;AAAA,EAAS;AAAA;AAAA,EAGxD;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAQ;AAAA,EAAO;AAAA,EAC3D;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAU;AAAA,EAAU;AAAA,EAAO;AAAA,EAAS;AAAA,EACtD;AAAA,EAAW;AAAA,EAAY;AAAA,EAAW;AAAA,EAAS;AAAA,EAAW;AAAA;AAAA,EAGtD;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAU;AAAA,EAAU;AAAA,EAAQ;AAAA,EAAS;AAAA,EACvD;AAAA,EAAU;AAAA,EAAU;AAAA,EAAa;AAAA,EAAY;AAAA,EAAU;AAAA,EACvD;AAAA,EAAU;AAAA,EAAY;AAAA,EAAU;AAAA,EAAU;AAAA,EAAU;AAAA;AAAA,EAGpD;AAAA,EAAU;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EAAS;AAAA,EAAS;AAAA,EAC3D;AAAA,EAAa;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAY;AAAA,EAAU;AAAA,EACpD;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EAAY;AAAA,EAAY;AAAA,EACvD;AAAA,EAAS;AAAA,EAAO;AAAA,EAAO;AAAA,EAAQ;AAAA,EAAQ;AAAA,EAAS;AAAA,EAAS;AAAA;AAAA,EAGzD;AAAA,EAAU;AAAA,EAAU;AAAA,EAAW;AAAA,EAAU;AAAA,EAAS;AAAA,EAClD;AAAA,EAAY;AAAA,EAAW;AAAA,EAAU;AAAA,EAAU;AAAA,EAAW;AAAA,EACtD;AAAA,EAAY;AAAA,EAAW;AAAA,EAAW;AAAA,EAAY;AAAA,EAC9C;AAAA,EAAU;AAAA,EAAU;AAAA,EAAS;AAAA,EAAS;AAAA,EAAS;AACjD;AAEA,SAAS,WAAW,MAA2B;AAC7C,MAAI;AACJ,KAAG;AAAE,QAAI,WAAW,KAAK,MAAM,KAAK,OAAO,IAAI,WAAW,MAAM,CAAC;AAAA,EAAa,SACvE,KAAK,IAAI,CAAC;AACjB,SAAO;AACT;AA0BA,SAASC,sBAAgC;AACvC,SAAO;AAAA,IACL,OAAO,CAAC;AAAA,IACR,OAAO;AAAA,IACP,OAAO;AAAA,IACP,OAAO;AAAA,IACP,YAAY;AAAA,IACZ,UAAU;AAAA,IACV,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,QAAQ;AAAA,IACR,OAAO;AAAA,IACP,SAAS;AAAA,IACT,cAAc;AAAA,IACd,WAAW,oBAAI,IAAI;AAAA,EACrB;AACF;AAEA,SAAS,WAAW,GAA6B;AAE/C,MAAI,OAAwB;AAC5B,aAAW,KAAK,EAAE,OAAO;AACvB,QAAI,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAK,QAAO;AAAA,EACxC;AACA,SAAO,MAAM,QAAQ;AACvB;AAIA,SAASC,QAAO,GAAoB;AAClC,MAAI,EAAE,UAAU,EAAE,SAAU;AAG5B,IAAE;AACF,MAAI,EAAE,cAAc,KAAK,IAAI,IAAI,KAAK,KAAK,MAAM,EAAE,QAAQ,EAAE,CAAC,GAAG;AAC/D,MAAE,aAAa;AACf,QAAI,EAAE,MAAM,SAAS,WAAW;AAC9B,YAAM,OAAO,IAAI,IAAI,EAAE,SAAS;AAChC,iBAAW,KAAK,EAAE,MAAO,MAAK,IAAI,EAAE,IAAI;AACxC,YAAM,OAAO,WAAW,IAAI;AAE5B,YAAM,WAAW,IAAI,IAAI,EAAE,MAAM,IAAI,CAAC,MAAM,EAAE,GAAG,CAAC;AAClD,UAAI,MAAM;AACV,eAAS,IAAI,SAAS,IAAI,QAAQ,KAAK;AACrC,YAAI,CAAC,SAAS,IAAI,CAAC,GAAG;AAAE,gBAAM;AAAG;AAAA,QAAO;AAAA,MAC1C;AACA,UAAI,OAAO,GAAG;AACZ,UAAE,MAAM,KAAK,EAAE,MAAM,KAAK,KAAK,SAAS,EAAE,CAAC;AAC3C,UAAE,UAAU,IAAI,IAAI;AAAA,MACtB;AAAA,IACF;AAAA,EACF;AAGA,aAAW,KAAK,EAAE,OAAO;AACvB,MAAE,OAAO,EAAE;AAAA,EACb;AAGA,QAAM,SAAS,EAAE,MAAM;AACvB,IAAE,QAAQ,EAAE,MAAM,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,KAAK,MAAM;AACtD,QAAM,UAAU,SAAS,EAAE,MAAM;AAGjC,MAAI,UAAU,GAAG;AACf,MAAE,SAAS;AACX,MAAE,QAAQ;AACV,MAAE,SAAS,WAAW,CAAC;AACvB,QAAI,EAAE,SAAS,GAAG;AAChB,QAAE,WAAW;AACb,QAAE,QAAQ,CAAC;AAAA,IACb;AAAA,EACF;AAGA,IAAE,SAAS,WAAW,CAAC;AAGvB,MAAI,EAAE,eAAe,GAAG;AACtB,MAAE;AACF,QAAI,EAAE,gBAAgB,EAAG,GAAE,UAAU;AAAA,EACvC;AACF;AAIA,SAAS,cAAc,GAAc,YAAsB,YAAoB,SAA2B;AACxG,QAAM,OAAiB,CAAC;AAExB,WAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,QAAI,OAAO;AAGX,QAAI,IAAI,SAAS;AACf,UAAI,IAAI,GAAG;AAET,cAAM,OAAO,WAAW,CAAC,KAAK,IAAI,OAAO,MAAM;AAC/C,eAAO,aAAa,SAAS,UAAU,CAAC,IAAI,GAAG;AAAA,MACjD,WAAW,MAAM,GAAG;AAElB,YAAI,EAAE,SAAS,GAAG;AAChB,gBAAM,YAAY,GAAG,EAAE,KAAK;AAC5B,gBAAM,MAAM,KAAK,OAAO,SAAS,UAAU,UAAU,CAAC;AACtD,gBAAM,aAAaF,eAAc,EAAE,QAAQA,eAAc,MAAM;AAC/D,gBAAM,MAAM,IAAI,OAAO,GAAG,IAAI,YAAY,IAAI,OAAO,SAAS,MAAM,UAAU,MAAM;AACpF,iBAAO,aAAa,SAAS,UAAU,CAAC,IAAI,GAAG;AAAA,QACjD,WAAW,EAAE,QAAQ;AACnB,gBAAM,YAAY;AAClB,gBAAM,MAAM,KAAK,OAAO,SAAS,UAAU,UAAU,CAAC;AACtD,iBAAO,IAAI,OAAO,GAAG,IAAI;AACzB,iBAAO,KAAK,OAAO,MAAM;AAAA,QAC3B;AAAA,MACF;AAEA,aAAO,KAAK,OAAO,MAAM;AAAA,IAC3B,OAAO;AAGL,UAAI,MAAM,WAAW,SAAS;AAC5B,cAAM,MAAM,KAAK,OAAO,SAAS,QAAQ,UAAU,CAAC;AACpD,cAAM,MAAM,IAAI,OAAO,GAAG,IAAI,UAAU,IAAI,OAAO,SAAS,MAAM,QAAQ,MAAM;AAChF,cAAM,WAAWA,eAAc,KAAK,MAAM,KAAK,OAAO,IAAIA,eAAc,MAAM,CAAC;AAC/E,eAAO,aAAa,SAAS,QAAQ,CAAC,IAAI,GAAG;AAAA,MAC/C,OAAO;AACL,iBAAS,IAAI,GAAG,IAAI,QAAQ,KAAK;AAC/B,gBAAM,OAAO,EAAE,MAAM,KAAK,CAAC,MAAM;AAC/B,kBAAM,UAAU,IAAI,KAAK,MAAM,EAAE,GAAG;AACpC,mBAAO,WAAW,KAAK,UAAU,EAAE,KAAK,UAAU,EAAE,QAAQ;AAAA,UAC9D,CAAC;AACD,cAAI,MAAM;AACR,kBAAM,UAAU,IAAI,KAAK,MAAM,KAAK,GAAG;AACvC,kBAAM,KAAK,KAAK,KAAK,OAAO;AAC5B,kBAAM,WAAW,KAAK,SAAS,EAAE;AACjC,kBAAM,WAAW,EAAE,WAAW,KAAK,OAAO,EAAE,MAAM,SAAS;AAC3D,kBAAM,UAAU,YAAY,UAAU;AACtC,gBAAI,UAAU;AACZ,sBAAQ,UAAU,WAAW,EAAE,YAAY,WAAW,EAAE;AAAA,YAC1D,OAAO;AACL,sBAAQ,WAAW,EAAE;AAAA,YACvB;AAAA,UACF,OAAO;AACL,oBAAQ;AAAA,UACV;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,SAAK,KAAK,IAAI;AAAA,EAChB;AACA,SAAO;AACT;AAQA,SAAS,WAAW,EAAE,QAAQ,QAAQ,GAAoB;AACxD,QAAM,WAAWG,QAAkBF,oBAAmB,CAAC;AACvD,QAAM,CAAC,MAAM,OAAO,IAAIG,UAAS,CAAC;AAClC,QAAM,CAAC,aAAa,cAAc,IAAIA,UAAS,CAAC;AAChD,QAAM,YAAYD,QAAO,OAAO;AAChC,YAAU,UAAU;AAGpB,EAAAE,WAAU,MAAM;AACd,UAAM,QAAQ,YAAY,MAAM;AAC9B,qBAAe,CAAC,UAAU,OAAO,KAAKL,eAAc,MAAM;AAAA,IAC5D,GAAG,GAAG;AACN,WAAO,MAAM,cAAc,KAAK;AAAA,EAClC,GAAG,CAAC,CAAC;AAGL,EAAAK,WAAU,MAAM;AACd,UAAM,WAAW,YAAY,MAAM;AACjC,MAAAH,QAAO,SAAS,OAAO;AACvB,cAAQ,CAAC,MAAM,IAAI,CAAC;AAAA,IACtB,GAAG,EAAE;AACL,WAAO,MAAM,cAAc,QAAQ;AAAA,EACrC,GAAG,CAAC,CAAC;AAEL,EAAAI;AAAA,IACEC,aAAY,CAAC,OAAO,QAAQ;AAC1B,YAAMC,KAAI,SAAS;AACnB,UAAIA,GAAE,UAAU;AACd,YAAI,UAAU,KAAK;AACjB,mBAAS,UAAUP,oBAAmB;AACtC,kBAAQ,CAAC;AAAA,QACX,WAAW,UAAU,OAAO,IAAI,QAAQ;AACtC,oBAAU,QAAQ;AAAA,QACpB;AACA;AAAA,MACF;AAEA,UAAK,UAAU,OAAO,IAAI,QAAS,UAAU,KAAK;AAChD,QAAAO,GAAE,SAAS,CAACA,GAAE;AACd;AAAA,MACF;AACA,UAAK,UAAU,OAAO,IAAI,QAAS,IAAI,QAAQ;AAC7C,kBAAU,QAAQ;AAClB;AAAA,MACF;AAEA,UAAIA,GAAE,OAAQ;AAGd,UAAI,MAAM,WAAW,KAAK,SAAS,OAAO,SAAS,KAAK;AAEtD,YAAI,CAACA,GAAE,QAAQ;AACb,UAAAA,GAAE,SAAS,WAAWA,EAAC;AAAA,QACzB;AACA,YAAIA,GAAE,QAAQ;AACZ,gBAAM,WAAWA,GAAE,OAAOA,GAAE,MAAM,MAAM;AACxC,cAAI,aAAa,OAAO;AACtB,YAAAA,GAAE,SAAS;AAEX,gBAAIA,GAAE,UAAUA,GAAE,QAAQ;AAExB,cAAAA,GAAE,QAAQA,GAAE,MAAM,OAAO,CAAC,MAAM,EAAE,SAASA,GAAE,MAAM;AACnD,cAAAA,GAAE;AAEF,oBAAM,YAAYA,GAAE;AACpB,oBAAM,UAAUA,GAAE,OAAO;AACzB,oBAAM,aAAaA,GAAE,SAAS,IAAIA,GAAE,QAAQ;AAC5C,cAAAA,GAAE,SAAS,UAAU;AACrB,cAAAA,GAAE,QAAQA,GAAE,QAAQ;AAGpB,oBAAM,gBAAgB,KAAK,MAAM,YAAY,GAAG;AAChD,oBAAM,eAAe,KAAK,MAAMA,GAAE,QAAQ,GAAG;AAC7C,kBAAI,eAAe,eAAe;AAChC,gBAAAA,GAAE,SAAS;AAAA,cACb;AAGA,kBAAIA,GAAE,SAAS,OAAU,YAAY,KAAQ;AAC3C,gBAAAA,GAAE,UAAU;AACZ,gBAAAA,GAAE,eAAe;AAAA,cACnB;AACA,cAAAA,GAAE,QAAQ;AACV,cAAAA,GAAE,SAAS,WAAWA,EAAC;AAAA,YACzB;AAAA,UACF,OAAO;AAEL,YAAAA,GAAE,QAAQ;AAAA,UACZ;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,CAAC,CAAC;AAAA,EACP;AAEA,QAAM,IAAI,SAAS;AACnB,QAAM,aAAaR,eAAc,WAAW;AAC5C,QAAM,WAAW,OAAO,EAAE,KAAK,EAAE,SAAS,GAAG,GAAG;AAChD,QAAM,aAAa,gBAAgB,QAAQ;AAC3C,QAAM,OAAO,cAAc,GAAG,YAAY,YAAY,EAAE,OAAO;AAE/D,OAAK;AAEL,SACE,gBAAAS,MAACC,MAAA,EAAI,eAAc,UAAS,UAAU,GAEpC;AAAA,oBAAAC,KAACD,MAAA,EAAI,eAAc,OACjB,0BAAAD,MAACG,OAAA,EAAK;AAAA;AAAA,MACD,gBAAAD,KAACC,OAAA,EAAK,OAAM,OAAO,mBAAI,OAAO,KAAK,IAAI,GAAG,EAAE,KAAK,CAAC,GAAE;AAAA,MACtD;AAAA,MAAK;AAAA,MAAG,gBAAAH,MAACG,OAAA,EAAK,OAAM,QAAO;AAAA;AAAA,QAAI,KAAK,MAAM,EAAE,QAAQ,EAAE;AAAA,SAAE;AAAA,OAC3D,GACF;AAAA,IAGC,CAAC,EAAE,YAAY,EAAE,UAChB,gBAAAD,KAACD,MAAA,EAAI,WAAW,GACd,0BAAAD,MAACG,OAAA,EAAK;AAAA;AAAA,MACA,gBAAAD,KAACC,OAAA,EAAK,OAAM,SAAS,YAAE,OAAM;AAAA,MACjC,gBAAAD,KAACC,OAAA,EAAK,OAAM,SAAS,YAAE,OAAO,MAAM,EAAE,MAAM,MAAM,GAAE;AAAA,OACtD,GACF;AAAA,IAIF,gBAAAH,MAACC,MAAA,EAAI,eAAc,UAAS,WAAW,GACrC;AAAA,sBAAAD,MAACG,OAAA,EAAK;AAAA;AAAA,QAAE,SAAI,OAAO,MAAM;AAAA,QAAE;AAAA,SAAC;AAAA,MAC3B,KAAK,IAAI,CAAC,KAAK,MACd,gBAAAD,KAACC,OAAA,EAAc,mBAAI,GAAG,YAAX,CAAe,CAC3B;AAAA,MACD,gBAAAH,MAACG,OAAA,EAAK;AAAA;AAAA,QAAE,SAAI,OAAO,MAAM;AAAA,QAAE;AAAA,SAAC;AAAA,OAC9B;AAAA,IAGC,EAAE,YACD,gBAAAH,MAACC,MAAA,EAAI,WAAW,GACd;AAAA,sBAAAC,KAACC,OAAA,EAAK,MAAI,MAAC,OAAM,OAAM,4CAEvB;AAAA,MACA,gBAAAH,MAACG,OAAA,EACE;AAAA;AAAA,QAAS,gBAAAD,KAACC,OAAA,EAAK,OAAM,UAAU,YAAE,OAAM;AAAA,QACvC;AAAA,SACH;AAAA,OACF;AAAA,IAIF,gBAAAD,KAACD,MAAA,EAAI,WAAW,GACd,0BAAAC,KAACC,OAAA,EAAK,UAAQ,MACX,uGACH,GACF;AAAA,KACF;AAEJ;AAIA,IAAO,sBAAQ;AAAA,EACb,IAAI;AAAA,EACJ,MAAM;AAAA,EACN,aAAa;AAAA,EACb,MAAM,YAAY;AAChB,UAAM,IAAI,QAAc,CAAC,YAAY;AACnC,YAAM,EAAE,QAAQ,IAAIC;AAAA,QAClB,gBAAAF,KAAC,cAAW,QAAQ,MAAM;AAAE,kBAAQ;AAAG,kBAAQ;AAAA,QAAG,GAAG;AAAA,MACvD;AAAA,IACF,CAAC;AAAA,EACH;AACF;;;AChcO,SAAS,YAAoB;AAClC,eAAa,qBAAY;AACzB,eAAa,mBAAU;AACvB,SAAO,UAAU;AACnB;;;AZFA,SAAS,UAAAG,eAAc;AACvB,OAAOC,YAAW;AAqCV,gBAAAC,YAAA;AAnCR,IAAM,cAAc,CAAC,QAAQ,OAAO,SAAS,QAAQ,cAAc,MAAM;AAElE,SAAS,YAAqB;AACnC,QAAMC,WAAU,IAAI,QAAQ;AAC5B,EAAAA,SAAQ,aAAa;AAErB,EAAAA,SACG,KAAK,SAAS,EACd,YAAY,kFAA2B,EACvC,QAAQ,SAAS,iBAAiB,gCAAO,EACzC,OAAO,aAAa,kDAAU,EAC9B,OAAO,mBAAmB,kDAAU;AAEvC,EAAAA,SAAQ,kBAAkB,MAAM,WAAWA,QAAO;AAElD,EAAAA,SAAQ,KAAK,aAAa,OAAO,gBAAgB;AAC/C,UAAM,MAAM,MAAM,qBAAqB,KAAK,WAAW;AACvD,IAAC,YAAmD,aAAa;AAAA,EACnE,CAAC;AAGD,EAAAA,SACG,QAAQ,MAAM,EACd,YAAY,wDAAW,EACvB,OAAO,iBAAkB;AACxB,QAAI,CAAC,QAAQ,MAAM,OAAO;AACxB,cAAQ,MAAM,+JAAiD;AAC/D,cAAQ,KAAK,CAAC;AAAA,IAChB;AAEA,UAAM,MAAO,KAA4C;AAIzD,UAAM,MAAM;AAAA,MACV,gBAAAD;AAAA,QAAC;AAAA;AAAA,UACC,eAAe,KAAK,OAAO,UAAU,UAAU;AAAA,UAC/C,WAAW,KAAK,OAAO,MAAM,UAAU;AAAA,UACvC,SAAS,KAAK,WAAW;AAAA;AAAA,MAC3B;AAAA,IACF;AAEA,UAAM,IAAI;AAAA,EACZ,CAAC;AAGH,EAAAC,SACG,QAAQ,KAAK,EACb,YAAY,4CAAS,EACrB,SAAS,eAAe,0BAAM,EAC9B,OAAO,kBAAkB,4CAAS,EAClC,OAAO,eAAgB,SAAmB;AACzC,YAAQ,IAAI,iEAAyB;AAAA,EACvC,CAAC;AAGH,EAAAA,SACG,QAAQ,OAAO,EACf,YAAY,sCAAQ,EACpB,OAAO,YAAY,kDAAe,EAClC,OAAO,UAAU,yCAAgB,EACjC,OAAO,iBAAkB;AACxB,YAAQ,IAAI,mEAA2B;AAAA,EACzC,CAAC;AAGH,EAAAA,SACG,QAAQ,MAAM,EACd,YAAY,2GAA2B,EACvC,OAAO,iBAAkB;AACxB,YAAQ,IAAI,kEAA0B;AAAA,EACxC,CAAC;AAGH,EAAAA,SACG,QAAQ,YAAY,EACpB,YAAY,yFAA6B,EACzC,SAAS,WAAW,sBAAY,eAAe,EAC/C,OAAO,eAAgB,OAAgB;AACtC,QAAI,CAAC,OAAO;AACV,cAAQ,IAAI,kGAA+D;AAC3E;AAAA,IACF;AACA,QAAI,UAAU,QAAQ;AACpB,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA,gCAIY,YAAY,KAAK,GAAG,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA,wCAKb;AAAA,IAClC,OAAO;AACL,cAAQ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,oCAagB;AAAA,IAC9B;AAAA,EACF,CAAC;AAGH,YAAU;AAEV,EAAAA,SACG,QAAQ,MAAM,EACd,YAAY,4CAAS,EACrB,SAAS,UAAU,8GAAoB,EACvC,OAAO,eAAgB,MAAe;AACrC,QAAI,MAAM;AACR,YAAM,OAAO,QAAQ,IAAI;AACzB,UAAI,CAAC,MAAM;AACT,gBAAQ,MAAM,mCAAU,IAAI,yFAA6B;AACzD,gBAAQ,KAAK,CAAC;AAAA,MAChB;AACA,cAAQ,IAAI,6BAAS,KAAK,IAAI,WAAM,KAAK,WAAW;AAAA,CAAI;AACxD,YAAM,KAAK,KAAK;AAAA,IAClB,OAAO;AACL,YAAM,QAAQ,UAAU;AACxB,UAAI,MAAM,WAAW,GAAG;AACtB,gBAAQ,IAAI,4CAAS;AACrB;AAAA,MACF;AAEA,YAAM,eAAe,MAAM,IAAI,QAAqB,CAAC,YAAY;AAC/D,cAAM,EAAE,QAAQ,IAAIH;AAAA,UAClB,gBAAAE;AAAA,YAAC;AAAA;AAAA,cACC;AAAA,cACA,UAAU,CAAC,SAAS;AAClB,wBAAQ;AACR,wBAAQ,IAAI;AAAA,cACd;AAAA,cACA,QAAQ,MAAM;AACZ,wBAAQ;AACR,wBAAQ,IAAI;AAAA,cACd;AAAA;AAAA,UACF;AAAA,QACF;AAAA,MACF,CAAC;AAED,UAAI,cAAc;AAChB,gBAAQ,IAAI;AAAA,8BAAaD,OAAM,MAAM,aAAa,IAAI,CAAC;AAAA,CAAI;AAC3D,cAAM,aAAa,KAAK;AAAA,MAC1B;AAAA,IACF;AAAA,EACF,CAAC;AAEH,SAAOE;AACT;;;AazKO,IAAM,WAAW;AAAA;AAAA,EAEtB,SAAS;AAAA;AAAA,EAET,eAAe;AAAA;AAAA,EAEf,cAAc;AAAA;AAAA,EAEd,QAAQ;AACV;;;ACLA,QAAQ,GAAG,UAAU,MAAM;AACzB,UAAQ,KAAK,SAAS,MAAM;AAC9B,CAAC;AAED,IAAM,UAAU,UAAU;AAE1B,IAAI;AACF,QAAM,QAAQ,WAAW,QAAQ,IAAI;AACvC,SAAS,KAAc;AACrB,QAAM,QAAQ;AAEd,MAAI,MAAM,SAAS,6BAA6B,MAAM,SAAS,qBAAqB;AAClF,YAAQ,KAAK,MAAM,YAAY,SAAS,OAAO;AAAA,EACjD;AAEA,MAAI,OAAO,MAAM,aAAa,UAAU;AACtC,YAAQ,KAAK,MAAM,QAAQ;AAAA,EAC7B;AAEA,UAAQ,MAAM,OAAO,GAAG,CAAC;AACzB,UAAQ,KAAK,SAAS,aAAa;AACrC;","names":["program","Text","jsxs","Box","Text","jsx","Box","Text","useEffect","useState","jsx","jsxs","Box","Text","useState","useCallback","jsx","jsxs","Box","Text","useInput","render","useState","useEffect","useCallback","jsx","jsxs","s","Box","Text","useInput","render","useState","useEffect","useRef","useCallback","jsx","jsxs","CYBER_PALETTE","createInitialState","update","useRef","useState","useEffect","useInput","useCallback","s","jsxs","Box","jsx","Text","render","render","chalk","jsx","program"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "dskcode",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"repository": {
|
|
5
|
+
"type": "git",
|
|
6
|
+
"url": "git+https://github.com/Awu12277/deepseek-agent-cli/tree/main"
|
|
7
|
+
},
|
|
4
8
|
"description": "A DeepSeek-native AI coding agent for your terminal",
|
|
5
9
|
"type": "module",
|
|
6
10
|
"bin": {
|