@hflin/cclin 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +124 -0
- package/dist/index.d.ts +10 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +165 -0
- package/dist/index.js.map +1 -0
- package/dist/llm/client.d.ts +32 -0
- package/dist/llm/client.d.ts.map +1 -0
- package/dist/llm/client.js +280 -0
- package/dist/llm/client.js.map +1 -0
- package/dist/runtime/compaction.d.ts +49 -0
- package/dist/runtime/compaction.d.ts.map +1 -0
- package/dist/runtime/compaction.js +118 -0
- package/dist/runtime/compaction.js.map +1 -0
- package/dist/runtime/compaction.test.d.ts +7 -0
- package/dist/runtime/compaction.test.d.ts.map +1 -0
- package/dist/runtime/compaction.test.js +70 -0
- package/dist/runtime/compaction.test.js.map +1 -0
- package/dist/runtime/history.d.ts +34 -0
- package/dist/runtime/history.d.ts.map +1 -0
- package/dist/runtime/history.js +63 -0
- package/dist/runtime/history.js.map +1 -0
- package/dist/runtime/hooks.d.ts +54 -0
- package/dist/runtime/hooks.d.ts.map +1 -0
- package/dist/runtime/hooks.js +113 -0
- package/dist/runtime/hooks.js.map +1 -0
- package/dist/runtime/hooks.test.d.ts +7 -0
- package/dist/runtime/hooks.test.d.ts.map +1 -0
- package/dist/runtime/hooks.test.js +73 -0
- package/dist/runtime/hooks.test.js.map +1 -0
- package/dist/runtime/model-profile.d.ts +42 -0
- package/dist/runtime/model-profile.d.ts.map +1 -0
- package/dist/runtime/model-profile.js +84 -0
- package/dist/runtime/model-profile.js.map +1 -0
- package/dist/runtime/prompt.d.ts +38 -0
- package/dist/runtime/prompt.d.ts.map +1 -0
- package/dist/runtime/prompt.js +152 -0
- package/dist/runtime/prompt.js.map +1 -0
- package/dist/runtime/prompt.md +64 -0
- package/dist/runtime/prompt.test.d.ts +7 -0
- package/dist/runtime/prompt.test.d.ts.map +1 -0
- package/dist/runtime/prompt.test.js +38 -0
- package/dist/runtime/prompt.test.js.map +1 -0
- package/dist/runtime/react-loop.d.ts +82 -0
- package/dist/runtime/react-loop.d.ts.map +1 -0
- package/dist/runtime/react-loop.js +311 -0
- package/dist/runtime/react-loop.js.map +1 -0
- package/dist/runtime/react-loop.test.d.ts +7 -0
- package/dist/runtime/react-loop.test.d.ts.map +1 -0
- package/dist/runtime/react-loop.test.js +78 -0
- package/dist/runtime/react-loop.test.js.map +1 -0
- package/dist/runtime/session.d.ts +109 -0
- package/dist/runtime/session.d.ts.map +1 -0
- package/dist/runtime/session.js +252 -0
- package/dist/runtime/session.js.map +1 -0
- package/dist/runtime/skills.d.ts +36 -0
- package/dist/runtime/skills.d.ts.map +1 -0
- package/dist/runtime/skills.js +187 -0
- package/dist/runtime/skills.js.map +1 -0
- package/dist/runtime/skills.test.d.ts +7 -0
- package/dist/runtime/skills.test.d.ts.map +1 -0
- package/dist/runtime/skills.test.js +92 -0
- package/dist/runtime/skills.test.js.map +1 -0
- package/dist/tools/approval.d.ts +61 -0
- package/dist/tools/approval.d.ts.map +1 -0
- package/dist/tools/approval.js +119 -0
- package/dist/tools/approval.js.map +1 -0
- package/dist/tools/approval.test.d.ts +9 -0
- package/dist/tools/approval.test.d.ts.map +1 -0
- package/dist/tools/approval.test.js +112 -0
- package/dist/tools/approval.test.js.map +1 -0
- package/dist/tools/bash.d.ts +6 -0
- package/dist/tools/bash.d.ts.map +1 -0
- package/dist/tools/bash.js +58 -0
- package/dist/tools/bash.js.map +1 -0
- package/dist/tools/edit-file.d.ts +6 -0
- package/dist/tools/edit-file.d.ts.map +1 -0
- package/dist/tools/edit-file.js +58 -0
- package/dist/tools/edit-file.js.map +1 -0
- package/dist/tools/get-memory.d.ts +9 -0
- package/dist/tools/get-memory.d.ts.map +1 -0
- package/dist/tools/get-memory.js +56 -0
- package/dist/tools/get-memory.js.map +1 -0
- package/dist/tools/list-directory.d.ts +6 -0
- package/dist/tools/list-directory.d.ts.map +1 -0
- package/dist/tools/list-directory.js +68 -0
- package/dist/tools/list-directory.js.map +1 -0
- package/dist/tools/mcp-client.d.ts +74 -0
- package/dist/tools/mcp-client.d.ts.map +1 -0
- package/dist/tools/mcp-client.js +129 -0
- package/dist/tools/mcp-client.js.map +1 -0
- package/dist/tools/mcp-config.d.ts +31 -0
- package/dist/tools/mcp-config.d.ts.map +1 -0
- package/dist/tools/mcp-config.js +55 -0
- package/dist/tools/mcp-config.js.map +1 -0
- package/dist/tools/mcp-registry.d.ts +39 -0
- package/dist/tools/mcp-registry.d.ts.map +1 -0
- package/dist/tools/mcp-registry.js +88 -0
- package/dist/tools/mcp-registry.js.map +1 -0
- package/dist/tools/orchestrator.d.ts +52 -0
- package/dist/tools/orchestrator.d.ts.map +1 -0
- package/dist/tools/orchestrator.js +190 -0
- package/dist/tools/orchestrator.js.map +1 -0
- package/dist/tools/orchestrator.test.d.ts +8 -0
- package/dist/tools/orchestrator.test.d.ts.map +1 -0
- package/dist/tools/orchestrator.test.js +122 -0
- package/dist/tools/orchestrator.test.js.map +1 -0
- package/dist/tools/read-file.d.ts +6 -0
- package/dist/tools/read-file.d.ts.map +1 -0
- package/dist/tools/read-file.js +50 -0
- package/dist/tools/read-file.js.map +1 -0
- package/dist/tools/registry.d.ts +55 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +75 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/registry.test.d.ts +8 -0
- package/dist/tools/registry.test.d.ts.map +1 -0
- package/dist/tools/registry.test.js +100 -0
- package/dist/tools/registry.test.js.map +1 -0
- package/dist/tools/router.d.ts +62 -0
- package/dist/tools/router.d.ts.map +1 -0
- package/dist/tools/router.js +119 -0
- package/dist/tools/router.js.map +1 -0
- package/dist/tools/router.test.d.ts +7 -0
- package/dist/tools/router.test.d.ts.map +1 -0
- package/dist/tools/router.test.js +102 -0
- package/dist/tools/router.test.js.map +1 -0
- package/dist/tools/safety.d.ts +16 -0
- package/dist/tools/safety.d.ts.map +1 -0
- package/dist/tools/safety.js +81 -0
- package/dist/tools/safety.js.map +1 -0
- package/dist/tools/safety.test.d.ts +7 -0
- package/dist/tools/safety.test.d.ts.map +1 -0
- package/dist/tools/safety.test.js +104 -0
- package/dist/tools/safety.test.js.map +1 -0
- package/dist/tools/search-files.d.ts +9 -0
- package/dist/tools/search-files.d.ts.map +1 -0
- package/dist/tools/search-files.js +114 -0
- package/dist/tools/search-files.js.map +1 -0
- package/dist/tools/update-plan.d.ts +9 -0
- package/dist/tools/update-plan.d.ts.map +1 -0
- package/dist/tools/update-plan.js +99 -0
- package/dist/tools/update-plan.js.map +1 -0
- package/dist/tools/write-file.d.ts +6 -0
- package/dist/tools/write-file.d.ts.map +1 -0
- package/dist/tools/write-file.js +41 -0
- package/dist/tools/write-file.js.map +1 -0
- package/dist/tui/app.d.ts +31 -0
- package/dist/tui/app.d.ts.map +1 -0
- package/dist/tui/app.js +121 -0
- package/dist/tui/app.js.map +1 -0
- package/dist/tui/chatwidget/markdown_renderer.d.ts +20 -0
- package/dist/tui/chatwidget/markdown_renderer.d.ts.map +1 -0
- package/dist/tui/chatwidget/markdown_renderer.js +188 -0
- package/dist/tui/chatwidget/markdown_renderer.js.map +1 -0
- package/dist/tui/cjk_text.d.ts +25 -0
- package/dist/tui/cjk_text.d.ts.map +1 -0
- package/dist/tui/cjk_text.js +84 -0
- package/dist/tui/cjk_text.js.map +1 -0
- package/dist/tui/cjk_text.test.d.ts +2 -0
- package/dist/tui/cjk_text.test.d.ts.map +1 -0
- package/dist/tui/cjk_text.test.js +62 -0
- package/dist/tui/cjk_text.test.js.map +1 -0
- package/dist/tui/composer_input.d.ts +31 -0
- package/dist/tui/composer_input.d.ts.map +1 -0
- package/dist/tui/composer_input.js +184 -0
- package/dist/tui/composer_input.js.map +1 -0
- package/dist/tui/composer_input.test.d.ts +2 -0
- package/dist/tui/composer_input.test.d.ts.map +1 -0
- package/dist/tui/composer_input.test.js +87 -0
- package/dist/tui/composer_input.test.js.map +1 -0
- package/dist/tui/input.d.ts +21 -0
- package/dist/tui/input.d.ts.map +1 -0
- package/dist/tui/input.js +166 -0
- package/dist/tui/input.js.map +1 -0
- package/dist/tui/output.d.ts +17 -0
- package/dist/tui/output.d.ts.map +1 -0
- package/dist/tui/output.js +104 -0
- package/dist/tui/output.js.map +1 -0
- package/dist/tui/state/chat_timeline.d.ts +50 -0
- package/dist/tui/state/chat_timeline.d.ts.map +1 -0
- package/dist/tui/state/chat_timeline.js +129 -0
- package/dist/tui/state/chat_timeline.js.map +1 -0
- package/dist/tui/types.d.ts +45 -0
- package/dist/tui/types.d.ts.map +1 -0
- package/dist/tui/types.js +14 -0
- package/dist/tui/types.js.map +1 -0
- package/dist/types.d.ts +435 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +8 -0
- package/dist/types.js.map +1 -0
- package/dist/utils/tokenizer.d.ts +21 -0
- package/dist/utils/tokenizer.d.ts.map +1 -0
- package/dist/utils/tokenizer.js +71 -0
- package/dist/utils/tokenizer.js.map +1 -0
- package/dist/utils/tokenizer.test.d.ts +7 -0
- package/dist/utils/tokenizer.test.d.ts.map +1 -0
- package/dist/utils/tokenizer.test.js +51 -0
- package/dist/utils/tokenizer.test.js.map +1 -0
- package/package.json +41 -0
- package/src/runtime/prompt.md +64 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safety.test.js","sourceRoot":"","sources":["../../src/tools/safety.test.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,YAAY,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,aAAa,CAAA;AAE5E,iFAAiF;AAEjF,QAAQ,CAAC,cAAc,EAAE,GAAG,EAAE;IAC1B,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,YAAY,CAAC,cAAc,CAAC,CAAA;QAC3C,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QACxD,MAAM,MAAM,GAAG,YAAY,CAAC,4BAA4B,CAAC,CAAA;QACzD,MAAM,CAAC,MAAM,CAAC,CAAC,OAAO,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sCAAsC,EAAE,GAAG,EAAE;QAC5C,MAAM,MAAM,GAAG,YAAY,CAAC,qBAAqB,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,gBAAgB,CAAC,CAAA;QACpD,CAAC;IACL,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mDAAmD,EAAE,GAAG,EAAE;QACzD,MAAM,MAAM,GAAG,YAAY,CAAC,eAAe,CAAC,CAAA;QAC5C,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yCAAyC,EAAE,GAAG,EAAE;QAC/C,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,CAAA;QACnC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;QAC7B,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;YACb,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,SAAS,CAAC,WAAW,CAAC,CAAA;QAC/C,CAAC;IACL,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kCAAkC,EAAE,GAAG,EAAE;QACxC,MAAM,MAAM,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;QACrC,MAAM,CAAC,MAAM,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA;AAEF,iFAAiF;AAEjF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uBAAuB,EAAE,GAAG,EAAE;QAC7B,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAC9C,MAAM,CAAC,eAAe,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IAC7D,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0CAA0C,EAAE,GAAG,EAAE;QAChD,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IAClD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yBAAyB,EAAE,GAAG,EAAE;QAC/B,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACxD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;IACtD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,4BAA4B,EAAE,GAAG,EAAE;QAClC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,wBAAwB,EAAE,GAAG,EAAE;QAC9B,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACzD,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA;AAEF,iFAAiF;AAEjF,QAAQ,CAAC,iBAAiB,EAAE,GAAG,EAAE;IAC7B,EAAE,CAAC,oBAAoB,EAAE,GAAG,EAAE;QAC1B,MAAM,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC9C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uCAAuC,EAAE,GAAG,EAAE;QAC7C,MAAM,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAChC,MAAM,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,2CAA2C,EAAE,GAAG,EAAE;QACjD,MAAM,CAAC,eAAe,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChE,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sBAAsB,EAAE,GAAG,EAAE;QAC5B,MAAM,CAAC,eAAe,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAChD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACnD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,GAAG,EAAE;QACpC,MAAM,CAAC,eAAe,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA;IACvD,CAAC,CAAC,CAAA;AACN,CAAC,CAAC,CAAA"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file search_files 工具 — 递归搜索文件名匹配。
|
|
3
|
+
*
|
|
4
|
+
* 参考 memo-code 的 search_files.ts,
|
|
5
|
+
* 用简单的 glob 匹配让 Agent 能快速定位文件。
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolDefinition } from '../types.js';
|
|
8
|
+
export declare const searchFilesTool: ToolDefinition;
|
|
9
|
+
//# sourceMappingURL=search-files.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-files.d.ts","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAoDjD,eAAO,MAAM,eAAe,EAAE,cAwE7B,CAAA"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file search_files 工具 — 递归搜索文件名匹配。
|
|
3
|
+
*
|
|
4
|
+
* 参考 memo-code 的 search_files.ts,
|
|
5
|
+
* 用简单的 glob 匹配让 Agent 能快速定位文件。
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs/promises';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { validatePath } from './safety.js';
|
|
10
|
+
/** 默认排除的目录。 */
|
|
11
|
+
const DEFAULT_EXCLUDES = new Set([
|
|
12
|
+
'node_modules', '.git', 'dist', '.next',
|
|
13
|
+
'__pycache__', '.venv', 'coverage',
|
|
14
|
+
]);
|
|
15
|
+
/** 最大返回条数。 */
|
|
16
|
+
const MAX_RESULTS = 100;
|
|
17
|
+
/**
|
|
18
|
+
* 简单 glob 匹配(仅支持 * 通配符)。
|
|
19
|
+
* 例如 `*.ts` 匹配 `foo.ts`,`test*` 匹配 `test-utils.ts`。
|
|
20
|
+
*/
|
|
21
|
+
function matchGlob(filename, pattern) {
|
|
22
|
+
const regex = pattern
|
|
23
|
+
.replace(/[.+^${}()|[\]\\]/g, '\\$&')
|
|
24
|
+
.replace(/\*/g, '.*');
|
|
25
|
+
return new RegExp(`^${regex}$`, 'i').test(filename);
|
|
26
|
+
}
|
|
27
|
+
/** 递归搜索目录。 */
|
|
28
|
+
async function searchDir(dir, pattern, results) {
|
|
29
|
+
if (results.length >= MAX_RESULTS)
|
|
30
|
+
return;
|
|
31
|
+
let entries;
|
|
32
|
+
try {
|
|
33
|
+
entries = await fs.readdir(dir, { withFileTypes: true, encoding: 'utf-8' });
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return; // 无权限等情况,静默跳过
|
|
37
|
+
}
|
|
38
|
+
for (const entry of entries) {
|
|
39
|
+
if (results.length >= MAX_RESULTS)
|
|
40
|
+
break;
|
|
41
|
+
if (entry.isDirectory()) {
|
|
42
|
+
if (DEFAULT_EXCLUDES.has(entry.name))
|
|
43
|
+
continue;
|
|
44
|
+
await searchDir(path.join(dir, entry.name), pattern, results);
|
|
45
|
+
}
|
|
46
|
+
else if (matchGlob(entry.name, pattern)) {
|
|
47
|
+
results.push(path.join(dir, entry.name));
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
export const searchFilesTool = {
|
|
52
|
+
name: 'search_files',
|
|
53
|
+
description: 'Recursively search files by glob pattern. ' +
|
|
54
|
+
'Returns matching file paths (max 100). ' +
|
|
55
|
+
'Automatically excludes node_modules, .git, dist.',
|
|
56
|
+
inputSchema: {
|
|
57
|
+
type: 'object',
|
|
58
|
+
properties: {
|
|
59
|
+
path: {
|
|
60
|
+
type: 'string',
|
|
61
|
+
description: 'Root directory to search from.',
|
|
62
|
+
},
|
|
63
|
+
pattern: {
|
|
64
|
+
type: 'string',
|
|
65
|
+
description: 'Glob pattern to match filenames ' +
|
|
66
|
+
'(e.g. "*.ts", "test*").',
|
|
67
|
+
},
|
|
68
|
+
},
|
|
69
|
+
required: ['path', 'pattern'],
|
|
70
|
+
},
|
|
71
|
+
isMutating: false,
|
|
72
|
+
async execute(input) {
|
|
73
|
+
const searchPath = String(input.path ?? '').trim();
|
|
74
|
+
const pattern = String(input.pattern ?? '').trim();
|
|
75
|
+
if (!searchPath) {
|
|
76
|
+
return { output: 'Error: path is required.', isError: true };
|
|
77
|
+
}
|
|
78
|
+
if (!pattern) {
|
|
79
|
+
return { output: 'Error: pattern is required.', isError: true };
|
|
80
|
+
}
|
|
81
|
+
const validation = validatePath(searchPath);
|
|
82
|
+
if (!validation.ok) {
|
|
83
|
+
return { output: validation.error, isError: true };
|
|
84
|
+
}
|
|
85
|
+
const resolved = path.resolve(searchPath);
|
|
86
|
+
try {
|
|
87
|
+
const stat = await fs.stat(resolved);
|
|
88
|
+
if (!stat.isDirectory()) {
|
|
89
|
+
return {
|
|
90
|
+
output: `Error: ${resolved} is not a directory.`,
|
|
91
|
+
isError: true,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
catch {
|
|
96
|
+
return {
|
|
97
|
+
output: `Error: directory not found: ${resolved}`,
|
|
98
|
+
isError: true,
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
const results = [];
|
|
102
|
+
await searchDir(resolved, pattern, results);
|
|
103
|
+
if (results.length === 0) {
|
|
104
|
+
return { output: 'No matches found.' };
|
|
105
|
+
}
|
|
106
|
+
const truncated = results.length >= MAX_RESULTS
|
|
107
|
+
? `\n(truncated at ${MAX_RESULTS} results)`
|
|
108
|
+
: '';
|
|
109
|
+
return {
|
|
110
|
+
output: results.join('\n') + truncated,
|
|
111
|
+
};
|
|
112
|
+
},
|
|
113
|
+
};
|
|
114
|
+
//# sourceMappingURL=search-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search-files.js","sourceRoot":"","sources":["../../src/tools/search-files.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file update_plan 工具 — 创建/更新结构化计划文件。
|
|
3
|
+
*
|
|
4
|
+
* Phase 10:让 Agent 能追踪多步任务的进度。
|
|
5
|
+
* 生成 Markdown 格式的计划清单,写入 .{plan_id}.plan.md。
|
|
6
|
+
*/
|
|
7
|
+
import type { ToolDefinition } from '../types.js';
|
|
8
|
+
export declare const updatePlanTool: ToolDefinition;
|
|
9
|
+
//# sourceMappingURL=update-plan.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-plan.d.ts","sourceRoot":"","sources":["../../src/tools/update-plan.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAgBjD,eAAO,MAAM,cAAc,EAAE,cA2F5B,CAAA"}
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file update_plan 工具 — 创建/更新结构化计划文件。
|
|
3
|
+
*
|
|
4
|
+
* Phase 10:让 Agent 能追踪多步任务的进度。
|
|
5
|
+
* 生成 Markdown 格式的计划清单,写入 .{plan_id}.plan.md。
|
|
6
|
+
*/
|
|
7
|
+
import * as fs from 'node:fs/promises';
|
|
8
|
+
import * as path from 'node:path';
|
|
9
|
+
import { validatePath } from './safety.js';
|
|
10
|
+
/** 状态 → Markdown checkbox 映射。 */
|
|
11
|
+
const STATUS_MAP = {
|
|
12
|
+
pending: '[ ]',
|
|
13
|
+
in_progress: '[/]',
|
|
14
|
+
done: '[x]',
|
|
15
|
+
};
|
|
16
|
+
export const updatePlanTool = {
|
|
17
|
+
name: 'update_plan',
|
|
18
|
+
description: 'Create or update a structured plan file (.plan.md) ' +
|
|
19
|
+
'in the project workspace. Use this to track multi-step ' +
|
|
20
|
+
'task progress with a checklist.',
|
|
21
|
+
inputSchema: {
|
|
22
|
+
type: 'object',
|
|
23
|
+
properties: {
|
|
24
|
+
plan_id: {
|
|
25
|
+
type: 'string',
|
|
26
|
+
description: 'Plan identifier, used as filename ' +
|
|
27
|
+
'(e.g. "refactor-auth" → .refactor-auth.plan.md).',
|
|
28
|
+
},
|
|
29
|
+
title: {
|
|
30
|
+
type: 'string',
|
|
31
|
+
description: 'Plan title (Markdown heading).',
|
|
32
|
+
},
|
|
33
|
+
steps: {
|
|
34
|
+
type: 'array',
|
|
35
|
+
description: 'Array of step objects. Each has: ' +
|
|
36
|
+
'description (string), ' +
|
|
37
|
+
'status ("pending"|"in_progress"|"done").',
|
|
38
|
+
items: { type: 'object' },
|
|
39
|
+
},
|
|
40
|
+
notes: {
|
|
41
|
+
type: 'string',
|
|
42
|
+
description: 'Optional notes section appended at end.',
|
|
43
|
+
},
|
|
44
|
+
},
|
|
45
|
+
required: ['plan_id', 'title', 'steps'],
|
|
46
|
+
},
|
|
47
|
+
isMutating: true,
|
|
48
|
+
async execute(input) {
|
|
49
|
+
const planId = String(input.plan_id ?? '').trim();
|
|
50
|
+
const title = String(input.title ?? '').trim();
|
|
51
|
+
const rawSteps = input.steps;
|
|
52
|
+
const notes = input.notes ? String(input.notes) : '';
|
|
53
|
+
if (!planId)
|
|
54
|
+
return { output: 'Error: plan_id is required.', isError: true };
|
|
55
|
+
if (!title)
|
|
56
|
+
return { output: 'Error: title is required.', isError: true };
|
|
57
|
+
if (!Array.isArray(rawSteps) || rawSteps.length === 0) {
|
|
58
|
+
return { output: 'Error: steps must be a non-empty array.', isError: true };
|
|
59
|
+
}
|
|
60
|
+
const filename = `.${planId}.plan.md`;
|
|
61
|
+
const validation = validatePath(filename);
|
|
62
|
+
if (!validation.ok)
|
|
63
|
+
return { output: validation.error, isError: true };
|
|
64
|
+
const resolved = path.resolve(filename);
|
|
65
|
+
// Build Markdown content
|
|
66
|
+
const lines = [
|
|
67
|
+
`# ${title}`,
|
|
68
|
+
'',
|
|
69
|
+
'## Steps',
|
|
70
|
+
'',
|
|
71
|
+
];
|
|
72
|
+
for (const step of rawSteps) {
|
|
73
|
+
const desc = String(step.description ?? '(no description)');
|
|
74
|
+
const status = STATUS_MAP[step.status] ?? STATUS_MAP.pending;
|
|
75
|
+
lines.push(`- ${status} ${desc}`);
|
|
76
|
+
}
|
|
77
|
+
if (notes) {
|
|
78
|
+
lines.push('', '## Notes', '', notes);
|
|
79
|
+
}
|
|
80
|
+
lines.push(''); // trailing newline
|
|
81
|
+
const content = lines.join('\n');
|
|
82
|
+
try {
|
|
83
|
+
await fs.writeFile(resolved, content, 'utf-8');
|
|
84
|
+
const done = rawSteps.filter((s) => s.status === 'done').length;
|
|
85
|
+
const total = rawSteps.length;
|
|
86
|
+
return {
|
|
87
|
+
output: `Plan updated: ${resolved}\n` +
|
|
88
|
+
`Progress: ${done}/${total} steps done.`,
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
return {
|
|
93
|
+
output: `update_plan failed: ${err.message}`,
|
|
94
|
+
isError: true,
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
//# sourceMappingURL=update-plan.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"update-plan.js","sourceRoot":"","sources":["../../src/tools/update-plan.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.d.ts","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAIH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAGjD,eAAO,MAAM,aAAa,EAAE,cAmC3B,CAAA"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file write_file 工具 — 写入/创建文件。
|
|
3
|
+
*/
|
|
4
|
+
import * as fs from 'node:fs/promises';
|
|
5
|
+
import * as path from 'node:path';
|
|
6
|
+
import { validatePath } from './safety.js';
|
|
7
|
+
export const writeFileTool = {
|
|
8
|
+
name: 'write_file',
|
|
9
|
+
description: 'Write content to a file. Creates the file and ' +
|
|
10
|
+
'parent directories if they do not exist. ' +
|
|
11
|
+
'Overwrites existing file content.',
|
|
12
|
+
inputSchema: {
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
path: { type: 'string', description: 'File path to write to.' },
|
|
16
|
+
content: { type: 'string', description: 'Content to write.' },
|
|
17
|
+
},
|
|
18
|
+
required: ['path', 'content'],
|
|
19
|
+
},
|
|
20
|
+
isMutating: true,
|
|
21
|
+
async execute(input) {
|
|
22
|
+
const filePath = String(input.path ?? '');
|
|
23
|
+
const content = String(input.content ?? '');
|
|
24
|
+
if (!filePath)
|
|
25
|
+
return { output: 'Error: path is required.', isError: true };
|
|
26
|
+
const validation = validatePath(filePath);
|
|
27
|
+
if (!validation.ok)
|
|
28
|
+
return { output: validation.error, isError: true };
|
|
29
|
+
const resolved = path.resolve(filePath);
|
|
30
|
+
try {
|
|
31
|
+
await fs.mkdir(path.dirname(resolved), { recursive: true });
|
|
32
|
+
await fs.writeFile(resolved, content, 'utf-8');
|
|
33
|
+
const lines = content.split('\n').length;
|
|
34
|
+
return { output: `File written: ${resolved} (${lines} lines, ${content.length} bytes)` };
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
return { output: `write_file failed: ${err.message}`, isError: true };
|
|
38
|
+
}
|
|
39
|
+
},
|
|
40
|
+
};
|
|
41
|
+
//# sourceMappingURL=write-file.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write-file.js","sourceRoot":"","sources":["../../src/tools/write-file.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,KAAK,EAAE,MAAM,kBAAkB,CAAA;AACtC,OAAO,KAAK,IAAI,MAAM,WAAW,CAAA;AAEjC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAE1C,MAAM,CAAC,MAAM,aAAa,GAAmB;IACzC,IAAI,EAAE,YAAY;IAClB,WAAW,EACP,gDAAgD;QAChD,2CAA2C;QAC3C,mCAAmC;IACvC,WAAW,EAAE;QACT,IAAI,EAAE,QAAQ;QACd,UAAU,EAAE;YACR,IAAI,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,wBAAwB,EAAE;YAC/D,OAAO,EAAE,EAAE,IAAI,EAAE,QAAQ,EAAE,WAAW,EAAE,mBAAmB,EAAE;SAChE;QACD,QAAQ,EAAE,CAAC,MAAM,EAAE,SAAS,CAAC;KAChC;IACD,UAAU,EAAE,IAAI;IAEhB,KAAK,CAAC,OAAO,CAAC,KAAK;QACf,MAAM,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,IAAI,EAAE,CAAC,CAAA;QACzC,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,OAAO,IAAI,EAAE,CAAC,CAAA;QAC3C,IAAI,CAAC,QAAQ;YAAE,OAAO,EAAE,MAAM,EAAE,0BAA0B,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAE3E,MAAM,UAAU,GAAG,YAAY,CAAC,QAAQ,CAAC,CAAA;QACzC,IAAI,CAAC,UAAU,CAAC,EAAE;YAAE,OAAO,EAAE,MAAM,EAAE,UAAU,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QAEtE,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAA;QAEvC,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAA;YAC3D,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,OAAO,EAAE,OAAO,CAAC,CAAA;YAC9C,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,CAAA;YACxC,OAAO,EAAE,MAAM,EAAE,iBAAiB,QAAQ,KAAK,KAAK,WAAW,OAAO,CAAC,MAAM,SAAS,EAAE,CAAA;QAC5F,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,OAAO,EAAE,MAAM,EAAE,sBAAuB,GAAa,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;QACpF,CAAC;IACL,CAAC;CACJ,CAAA"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file 主 App 组件 — Ink TUI 入口。
|
|
3
|
+
*
|
|
4
|
+
* Phase 8 升级:useReducer 状态管理 + dispatch actions。
|
|
5
|
+
* 核心思路:通过 AgentMiddleware 接收 Hook 事件 → dispatch action → 重新渲染。
|
|
6
|
+
*/
|
|
7
|
+
import type { AgentMiddleware, ApprovalRequest, ApprovalDecision } from '../types.js';
|
|
8
|
+
export type AppProps = {
|
|
9
|
+
/** 当前使用的模型名称,用于 Header 展示 */
|
|
10
|
+
model: string;
|
|
11
|
+
/** OpenAI 兼容 API 的 base URL */
|
|
12
|
+
baseURL: string;
|
|
13
|
+
/** 已注册工具的数量,用于 Header 展示 */
|
|
14
|
+
toolCount: number;
|
|
15
|
+
/** 工具审批策略(如 "auto" / "manual"),用于 Header 展示 */
|
|
16
|
+
approvalPolicy: string;
|
|
17
|
+
/** 当前工作目录,用于 Header 展示 */
|
|
18
|
+
cwd: string;
|
|
19
|
+
/** 用户提交输入时的处理函数(由 Session 提供) */
|
|
20
|
+
onSubmit: (input: string) => Promise<void>;
|
|
21
|
+
/** 用户输入 "exit" 时触发,用于通知外层清理资源 */
|
|
22
|
+
onExit: () => void;
|
|
23
|
+
/** TUI 中间件就绪时的回调,将中间件注册到 Session */
|
|
24
|
+
onMiddlewareReady: (mw: AgentMiddleware) => void;
|
|
25
|
+
/** 审批回调就绪时的回调,将 requestApproval 函数注入 Session */
|
|
26
|
+
onApprovalReady: (requestApproval: (req: ApprovalRequest) => Promise<ApprovalDecision>) => void;
|
|
27
|
+
/** 流式 chunk 处理器就绪时的回调,用于接收 assistant 增量文本 */
|
|
28
|
+
onAssistantChunkReady: (handler: (step: number, chunk: string) => void) => void;
|
|
29
|
+
};
|
|
30
|
+
export declare function App({ model, baseURL, toolCount, approvalPolicy, cwd, onSubmit, onExit, onMiddlewareReady, onApprovalReady, onAssistantChunkReady, }: AppProps): import("react/jsx-runtime").JSX.Element;
|
|
31
|
+
//# sourceMappingURL=app.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.d.ts","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"AAAA;;;;;GAKG;AAYH,OAAO,KAAK,EACR,eAAe,EACf,eAAe,EACf,gBAAgB,EACnB,MAAM,aAAa,CAAA;AAIpB,MAAM,MAAM,QAAQ,GAAG;IACnB,6BAA6B;IAC7B,KAAK,EAAE,MAAM,CAAA;IACb,+BAA+B;IAC/B,OAAO,EAAE,MAAM,CAAA;IACf,4BAA4B;IAC5B,SAAS,EAAE,MAAM,CAAA;IACjB,+CAA+C;IAC/C,cAAc,EAAE,MAAM,CAAA;IACtB,0BAA0B;IAC1B,GAAG,EAAE,MAAM,CAAA;IACX,iCAAiC;IACjC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAA;IAC1C,iCAAiC;IACjC,MAAM,EAAE,MAAM,IAAI,CAAA;IAClB,oCAAoC;IACpC,iBAAiB,EAAE,CAAC,EAAE,EAAE,eAAe,KAAK,IAAI,CAAA;IAChD,gDAAgD;IAChD,eAAe,EAAE,CACb,eAAe,EAAE,CAAC,GAAG,EAAE,eAAe,KAAK,OAAO,CAAC,gBAAgB,CAAC,KACnE,IAAI,CAAA;IACT,6CAA6C;IAC7C,qBAAqB,EAAE,CACnB,OAAO,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,KAAK,IAAI,KAC7C,IAAI,CAAA;CACZ,CAAA;AAID,wBAAgB,GAAG,CAAC,EAChB,KAAK,EACL,OAAO,EACP,SAAS,EACT,cAAc,EACd,GAAG,EACH,QAAQ,EACR,MAAM,EACN,iBAAiB,EACjB,eAAe,EACf,qBAAqB,GACxB,EAAE,QAAQ,2CA8IV"}
|
package/dist/tui/app.js
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
/**
|
|
3
|
+
* @file 主 App 组件 — Ink TUI 入口。
|
|
4
|
+
*
|
|
5
|
+
* Phase 8 升级:useReducer 状态管理 + dispatch actions。
|
|
6
|
+
* 核心思路:通过 AgentMiddleware 接收 Hook 事件 → dispatch action → 重新渲染。
|
|
7
|
+
*/
|
|
8
|
+
import React, { useCallback, useReducer, useRef } from 'react';
|
|
9
|
+
import { Box, useApp } from 'ink';
|
|
10
|
+
import { OutputArea } from './output.js';
|
|
11
|
+
import { InputArea } from './input.js';
|
|
12
|
+
import { chatTimelineReducer, createInitialState, } from './state/chat_timeline.js';
|
|
13
|
+
import { TOOL_STATUS } from './types.js';
|
|
14
|
+
// ─── App 组件 ─────────────────────────────────────────────────────────────
|
|
15
|
+
export function App({ model, baseURL, toolCount, approvalPolicy, cwd, onSubmit, onExit, onMiddlewareReady, onApprovalReady, onAssistantChunkReady, }) {
|
|
16
|
+
const { exit } = useApp();
|
|
17
|
+
// useReducer 状态管理
|
|
18
|
+
const [timeline, dispatchTimeline] = useReducer(chatTimelineReducer, undefined, createInitialState);
|
|
19
|
+
const [busy, setBusy] = React.useState(false);
|
|
20
|
+
const [contextPercent, setContextPercent] = React.useState(0);
|
|
21
|
+
const [activityTick, setActivityTick] = React.useState(0);
|
|
22
|
+
// 审批状态
|
|
23
|
+
const [approvalPending, setApprovalPending] = React.useState(false);
|
|
24
|
+
const [approvalText, setApprovalText] = React.useState('');
|
|
25
|
+
const approvalResolver = useRef(null);
|
|
26
|
+
const currentTurnRef = useRef(0);
|
|
27
|
+
const dispatch = useCallback((action) => {
|
|
28
|
+
dispatchTimeline(action);
|
|
29
|
+
}, []);
|
|
30
|
+
// 构建 TUI 中间件(Hook 事件 → dispatch actions)
|
|
31
|
+
const tuiMiddleware = React.useMemo(() => ({
|
|
32
|
+
name: 'tui',
|
|
33
|
+
onTurnStart: ({ turn, input }) => {
|
|
34
|
+
setBusy(true);
|
|
35
|
+
currentTurnRef.current = turn;
|
|
36
|
+
dispatch({ type: 'turn_start', turn, input });
|
|
37
|
+
},
|
|
38
|
+
onAction: ({ turn, step, action, thinking }) => {
|
|
39
|
+
setActivityTick(t => t + 1);
|
|
40
|
+
dispatch({
|
|
41
|
+
type: 'tool_action',
|
|
42
|
+
turn,
|
|
43
|
+
step,
|
|
44
|
+
action: { tool: action.tool, input: action.input },
|
|
45
|
+
thinking,
|
|
46
|
+
});
|
|
47
|
+
},
|
|
48
|
+
onObservation: ({ turn, step, tool, observation }) => {
|
|
49
|
+
dispatch({
|
|
50
|
+
type: 'tool_observation',
|
|
51
|
+
turn,
|
|
52
|
+
step,
|
|
53
|
+
observation,
|
|
54
|
+
toolStatus: TOOL_STATUS.SUCCESS,
|
|
55
|
+
});
|
|
56
|
+
},
|
|
57
|
+
onFinal: ({ turn, finalText, status }) => {
|
|
58
|
+
dispatch({
|
|
59
|
+
type: 'turn_final',
|
|
60
|
+
turn,
|
|
61
|
+
finalText,
|
|
62
|
+
status,
|
|
63
|
+
});
|
|
64
|
+
setBusy(false);
|
|
65
|
+
},
|
|
66
|
+
onContextUsage: ({ usagePercent }) => {
|
|
67
|
+
setContextPercent(usagePercent);
|
|
68
|
+
},
|
|
69
|
+
onContextCompacted: ({ status, beforeTokens, afterTokens, reductionPercent }) => {
|
|
70
|
+
if (status === 'success') {
|
|
71
|
+
dispatch({
|
|
72
|
+
type: 'append_system_message',
|
|
73
|
+
title: 'Context compacted',
|
|
74
|
+
content: `${beforeTokens} → ${afterTokens} tokens (-${reductionPercent}%)`,
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
}), [dispatch]);
|
|
79
|
+
// 审批回调
|
|
80
|
+
const requestApproval = useCallback((req) => {
|
|
81
|
+
return new Promise(resolve => {
|
|
82
|
+
setApprovalText(`${req.toolName}: ${req.reason}`);
|
|
83
|
+
setApprovalPending(true);
|
|
84
|
+
approvalResolver.current = resolve;
|
|
85
|
+
});
|
|
86
|
+
}, []);
|
|
87
|
+
// 组件挂载时注册中间件、审批回调和流式回调
|
|
88
|
+
React.useEffect(() => {
|
|
89
|
+
onMiddlewareReady(tuiMiddleware);
|
|
90
|
+
onApprovalReady(requestApproval);
|
|
91
|
+
onAssistantChunkReady((step, chunk) => {
|
|
92
|
+
setActivityTick(t => t + 1);
|
|
93
|
+
dispatch({
|
|
94
|
+
type: 'assistant_chunk',
|
|
95
|
+
turn: currentTurnRef.current,
|
|
96
|
+
step,
|
|
97
|
+
chunk,
|
|
98
|
+
});
|
|
99
|
+
});
|
|
100
|
+
}, [tuiMiddleware, requestApproval, onMiddlewareReady, onApprovalReady, onAssistantChunkReady, dispatch]);
|
|
101
|
+
// 审批响应处理
|
|
102
|
+
const handleApproval = useCallback((approved) => {
|
|
103
|
+
if (approvalResolver.current) {
|
|
104
|
+
approvalResolver.current(approved ? 'approve' : 'deny');
|
|
105
|
+
approvalResolver.current = null;
|
|
106
|
+
}
|
|
107
|
+
setApprovalPending(false);
|
|
108
|
+
setApprovalText('');
|
|
109
|
+
}, []);
|
|
110
|
+
// 提交处理
|
|
111
|
+
const handleSubmit = useCallback(async (input) => {
|
|
112
|
+
if (input.toLowerCase() === 'exit') {
|
|
113
|
+
onExit();
|
|
114
|
+
exit();
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
await onSubmit(input);
|
|
118
|
+
}, [onSubmit, onExit, exit]);
|
|
119
|
+
return (_jsxs(Box, { flexDirection: "column", padding: 1, children: [_jsx(OutputArea, { turns: timeline.turns, systemMessages: timeline.systemMessages, modelName: model, toolCount: toolCount, approvalPolicy: approvalPolicy, cwd: cwd }), _jsx(InputArea, { busy: busy, onSubmit: handleSubmit, approvalPending: approvalPending, approvalText: approvalText, onApproval: handleApproval, contextPercent: contextPercent, activityTick: activityTick })] }));
|
|
120
|
+
}
|
|
121
|
+
//# sourceMappingURL=app.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"app.js","sourceRoot":"","sources":["../../src/tui/app.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file Markdown 渲染器 — 将 Markdown 文本解析为 Ink 组件。
|
|
3
|
+
*
|
|
4
|
+
* 自写 parser(正则逐行解析),不依赖外部库。
|
|
5
|
+
* 参考 memo-code/packages/tui/src/chatwidget/MarkdownRenderer.tsx
|
|
6
|
+
*
|
|
7
|
+
* 支持:
|
|
8
|
+
* - heading (# ## ###)
|
|
9
|
+
* - paragraph
|
|
10
|
+
* - code block (```)
|
|
11
|
+
* - list (- * •)
|
|
12
|
+
* - blockquote (>)
|
|
13
|
+
* - horizontal rule (---)
|
|
14
|
+
* - inline: **bold**, *italic*, `code`, [link](url)
|
|
15
|
+
*/
|
|
16
|
+
import React from 'react';
|
|
17
|
+
export declare const MarkdownRenderer: React.NamedExoticComponent<{
|
|
18
|
+
content: string;
|
|
19
|
+
}>;
|
|
20
|
+
//# sourceMappingURL=markdown_renderer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"markdown_renderer.d.ts","sourceRoot":"","sources":["../../../src/tui/chatwidget/markdown_renderer.tsx"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,OAAO,KAAe,MAAM,OAAO,CAAA;AAqPnC,eAAO,MAAM,gBAAgB;aAGhB,MAAM;EAUjB,CAAA"}
|