@linghun/tools 0.1.0 → 0.1.2

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.
@@ -1,24 +1,30 @@
1
- import {
2
- WebSearchTool
3
- } from "./chunk-4EZHIDZ6.js";
4
1
  import {
5
2
  WriteTool
6
3
  } from "./chunk-I3Z4OKMS.js";
7
- import {
8
- MultiEditTool
9
- } from "./chunk-VJDLOFCF.js";
10
4
  import {
11
5
  WebFetchTool
12
6
  } from "./chunk-LGZOG7IQ.js";
7
+ import {
8
+ WebSearchTool
9
+ } from "./chunk-4EZHIDZ6.js";
10
+ import {
11
+ ReadSnippetsTool
12
+ } from "./chunk-GI5XI4HN.js";
13
+ import {
14
+ SourcePackTool
15
+ } from "./chunk-A6FUAM64.js";
16
+ import {
17
+ TodoTool
18
+ } from "./chunk-MFHY7PBM.js";
13
19
  import {
14
20
  GrepTool
15
21
  } from "./chunk-AZCQL24J.js";
16
22
  import {
17
- ReadTool
18
- } from "./chunk-RBHQ5WNR.js";
23
+ MultiEditTool
24
+ } from "./chunk-VJDLOFCF.js";
19
25
  import {
20
- TodoTool
21
- } from "./chunk-4567YAXM.js";
26
+ ReadTool
27
+ } from "./chunk-TZ6QK52L.js";
22
28
  import {
23
29
  GlobTool
24
30
  } from "./chunk-DN3KJZRV.js";
@@ -35,6 +41,8 @@ import {
35
41
  // src/tools/ui.ts
36
42
  var toolUserFacingNames = {
37
43
  Read: ReadTool.userFacingName,
44
+ ReadSnippets: ReadSnippetsTool.userFacingName,
45
+ SourcePack: SourcePackTool.userFacingName,
38
46
  Write: WriteTool.userFacingName,
39
47
  Edit: EditTool.userFacingName,
40
48
  MultiEdit: MultiEditTool.userFacingName,
@@ -0,0 +1,11 @@
1
+ import {
2
+ prompt
3
+ } from "./chunk-YCO6C7KF.js";
4
+
5
+ // src/tools/SourcePack/SourcePackTool.ts
6
+ var userFacingName = "\u5B9A\u4F4D\u4EE3\u7801\u7247\u6BB5";
7
+ var SourcePackTool = { name: "SourcePack", prompt, userFacingName };
8
+
9
+ export {
10
+ SourcePackTool
11
+ };
@@ -1,24 +1,30 @@
1
- import {
2
- WebSearchTool
3
- } from "./chunk-4EZHIDZ6.js";
4
1
  import {
5
2
  WriteTool
6
3
  } from "./chunk-I3Z4OKMS.js";
7
- import {
8
- MultiEditTool
9
- } from "./chunk-VJDLOFCF.js";
10
4
  import {
11
5
  WebFetchTool
12
6
  } from "./chunk-LGZOG7IQ.js";
7
+ import {
8
+ WebSearchTool
9
+ } from "./chunk-4EZHIDZ6.js";
10
+ import {
11
+ ReadSnippetsTool
12
+ } from "./chunk-GI5XI4HN.js";
13
+ import {
14
+ SourcePackTool
15
+ } from "./chunk-A6FUAM64.js";
16
+ import {
17
+ TodoTool
18
+ } from "./chunk-MFHY7PBM.js";
13
19
  import {
14
20
  GrepTool
15
21
  } from "./chunk-AZCQL24J.js";
16
22
  import {
17
- ReadTool
18
- } from "./chunk-RBHQ5WNR.js";
23
+ MultiEditTool
24
+ } from "./chunk-VJDLOFCF.js";
19
25
  import {
20
- TodoTool
21
- } from "./chunk-4567YAXM.js";
26
+ ReadTool
27
+ } from "./chunk-TZ6QK52L.js";
22
28
  import {
23
29
  GlobTool
24
30
  } from "./chunk-DN3KJZRV.js";
@@ -35,6 +41,8 @@ import {
35
41
  // src/tools/prompts.ts
36
42
  var toolPrompts = {
37
43
  Read: ReadTool.prompt,
44
+ ReadSnippets: ReadSnippetsTool.prompt,
45
+ SourcePack: SourcePackTool.prompt,
38
46
  Write: WriteTool.prompt,
39
47
  Edit: EditTool.prompt,
40
48
  MultiEdit: MultiEditTool.prompt,
@@ -0,0 +1,11 @@
1
+ import {
2
+ prompt
3
+ } from "./chunk-WEWXKRKL.js";
4
+
5
+ // src/tools/ReadSnippets/ReadSnippetsTool.ts
6
+ var userFacingName = "\u8BFB\u53D6\u4EE3\u7801\u7247\u6BB5";
7
+ var ReadSnippetsTool = { name: "ReadSnippets", prompt, userFacingName };
8
+
9
+ export {
10
+ ReadSnippetsTool
11
+ };
@@ -0,0 +1,6 @@
1
+ // src/tools/ReadSnippets/prompt.ts
2
+ var prompt = "Use ReadSnippets to read multiple known file line ranges in one call. Prefer it after search, index, or codebase-memory hits return path/range candidates.";
3
+
4
+ export {
5
+ prompt
6
+ };
@@ -0,0 +1,6 @@
1
+ // src/tools/SourcePack/prompt.ts
2
+ var prompt = "Use SourcePack to locate a small evidence pack of candidate source snippets for a query. If index/codebase-memory already returned paths or ranges, call ReadSnippets on those candidates first.";
3
+
4
+ export {
5
+ prompt
6
+ };
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ import type { ChildProcess } from "node:child_process";
1
2
  import { type ToolDefinition } from "./tool-runtime.js";
2
3
  export type { ToolDefinition, ToolFactoryDefinition, ToolInterruptBehavior, ToolLifecycleMetadata, ToolPermissionDecision, } from "./tool-runtime.js";
3
4
  export { createTool } from "./tool-runtime.js";
@@ -24,23 +25,41 @@ export type ToolProgressEvent = {
24
25
  stream: "stdout" | "stderr" | "system";
25
26
  text: string;
26
27
  };
28
+ export type ToolChildProcessTrackOptions = {
29
+ detached?: boolean;
30
+ label?: string;
31
+ cwd?: string;
32
+ retainAfterExit?: boolean;
33
+ };
27
34
  export type ReadSnapshot = {
28
35
  path: string;
29
36
  hash: string;
30
37
  mtimeMs: number;
31
38
  size: number;
32
39
  };
40
+ export type SourcePackCandidate = {
41
+ path: string;
42
+ start: number;
43
+ end: number;
44
+ reason?: string;
45
+ confidence?: number;
46
+ };
33
47
  export type ToolContext = {
34
48
  workspaceRoot: string;
35
49
  logRoot?: string;
36
50
  changedFiles: string[];
37
51
  todos: TodoItem[];
38
52
  readSnapshots?: Record<string, ReadSnapshot>;
53
+ sourcePackCandidates?: SourcePackCandidate[];
39
54
  patchSummaries?: Record<string, DiffSummary>;
40
55
  abortSignal?: AbortSignal;
41
56
  onProgress?: (event: ToolProgressEvent) => void | Promise<void>;
57
+ trackChildProcess?: (child: Pick<ChildProcess, "kill" | "pid" | "exitCode" | "signalCode" | "once">, options?: ToolChildProcessTrackOptions) => boolean;
58
+ };
59
+ export type ToolContextOptions = {
60
+ sourcePackCandidates?: SourcePackCandidate[];
42
61
  };
43
- export type ToolName = "Read" | "Write" | "Edit" | "MultiEdit" | "Grep" | "Glob" | "Bash" | "Todo" | "Diff" | "WebSearch" | "WebFetch";
62
+ export type ToolName = "Read" | "ReadSnippets" | "SourcePack" | "Write" | "Edit" | "MultiEdit" | "Grep" | "Glob" | "Bash" | "Todo" | "Diff" | "WebSearch" | "WebFetch";
44
63
  export type TodoStatus = "pending" | "in_progress" | "completed" | "blocked";
45
64
  export type TodoItem = {
46
65
  id: string;
@@ -60,6 +79,17 @@ export type ReadInput = {
60
79
  offset?: number;
61
80
  limit?: number;
62
81
  };
82
+ export type ReadSnippetsInput = {
83
+ ranges: {
84
+ path: string;
85
+ start: number;
86
+ end: number;
87
+ }[];
88
+ };
89
+ export type SourcePackInput = {
90
+ query: string;
91
+ limit?: number;
92
+ };
63
93
  export type WriteInput = {
64
94
  path: string;
65
95
  content: string;
@@ -117,7 +147,7 @@ export type ToolRunResult = {
117
147
  output: ToolOutput;
118
148
  };
119
149
  export declare const toolRegistryStatus: "ready";
120
- export declare function createToolContext(workspaceRoot?: string): ToolContext;
150
+ export declare function createToolContext(workspaceRoot?: string, options?: ToolContextOptions): ToolContext;
121
151
  /**
122
152
  * **UNSAFE LOW-LEVEL PRIMITIVE.** Executes a built-in tool directly without
123
153
  * any permission policy check.
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,42 +1,46 @@
1
+ import {
2
+ formatFetchOutput,
3
+ webFetch
4
+ } from "./chunk-4UHQWBFA.js";
1
5
  import {
2
6
  applyDomainFilter,
3
7
  bingSearch,
4
8
  formatSearchOutput
5
9
  } from "./chunk-EPIB4FSE.js";
6
- import {
7
- formatFetchOutput,
8
- webFetch
9
- } from "./chunk-4UHQWBFA.js";
10
10
  import {
11
11
  createTool
12
12
  } from "./chunk-MMJX44V6.js";
13
13
  import {
14
14
  toolPrompts
15
- } from "./chunk-KGDJAST5.js";
15
+ } from "./chunk-DWXJBDPQ.js";
16
16
  import {
17
17
  toolUserFacingNames
18
- } from "./chunk-NKWRH36V.js";
19
- import "./chunk-4EZHIDZ6.js";
20
- import "./chunk-YR4HWOR2.js";
21
- import "./chunk-VAFW24RN.js";
18
+ } from "./chunk-2R75FXZG.js";
22
19
  import "./chunk-I3Z4OKMS.js";
23
20
  import "./chunk-PS2ZOFZ6.js";
24
21
  import "./chunk-NPKLGVDQ.js";
25
- import "./chunk-VJDLOFCF.js";
26
- import "./chunk-3RP665TH.js";
27
- import "./chunk-IOC3BSPT.js";
28
22
  import "./chunk-LGZOG7IQ.js";
29
23
  import "./chunk-ZYAEUABC.js";
30
24
  import "./chunk-SWK6XRZQ.js";
25
+ import "./chunk-4EZHIDZ6.js";
26
+ import "./chunk-YR4HWOR2.js";
27
+ import "./chunk-VAFW24RN.js";
28
+ import "./chunk-GI5XI4HN.js";
29
+ import "./chunk-WEWXKRKL.js";
30
+ import "./chunk-A6FUAM64.js";
31
+ import "./chunk-YCO6C7KF.js";
32
+ import "./chunk-MFHY7PBM.js";
33
+ import "./chunk-SZFZPQGL.js";
34
+ import "./chunk-XZWSO5CM.js";
31
35
  import "./chunk-AZCQL24J.js";
32
36
  import "./chunk-HUIZOB4A.js";
33
37
  import "./chunk-MK3YP2VR.js";
34
- import "./chunk-RBHQ5WNR.js";
35
- import "./chunk-HNIVNZIS.js";
38
+ import "./chunk-VJDLOFCF.js";
39
+ import "./chunk-3RP665TH.js";
40
+ import "./chunk-IOC3BSPT.js";
41
+ import "./chunk-TZ6QK52L.js";
36
42
  import "./chunk-K3YDFDLP.js";
37
- import "./chunk-4567YAXM.js";
38
- import "./chunk-XZWSO5CM.js";
39
- import "./chunk-SZFZPQGL.js";
43
+ import "./chunk-HNIVNZIS.js";
40
44
  import "./chunk-DN3KJZRV.js";
41
45
  import "./chunk-2U4BZXAI.js";
42
46
  import "./chunk-ITBZHMZQ.js";
@@ -59,6 +63,13 @@ var toolRegistryStatus = "ready";
59
63
  var DEFAULT_LIMIT = 200;
60
64
  var DEFAULT_SEARCH_LIMIT = 100;
61
65
  var DEFAULT_TOOL_TEXT_LIMIT = 5e4;
66
+ var MAX_READ_SNIPPET_RANGES = 20;
67
+ var MAX_READ_SNIPPET_LINES = 120;
68
+ var MAX_READ_SNIPPET_OUTPUT_CHARS = 2e5;
69
+ var SOURCE_PACK_DEFAULT_LIMIT = 6;
70
+ var SOURCE_PACK_MAX_LIMIT = 12;
71
+ var SOURCE_PACK_CONTEXT_LINES = 8;
72
+ var SOURCE_PACK_MAX_TERMS = 6;
62
73
  var BASH_PREVIEW_LIMIT = 3e4;
63
74
  var BASH_TIMEOUT_MS = 12e4;
64
75
  var MAX_TODO_ITEMS = 100;
@@ -66,12 +77,13 @@ var SEARCH_EXCLUDED_DIR_NAMES = ["node_modules", "dist", ".git", ".codebase-memo
66
77
  var SEARCH_EXCLUDED_PATH_PREFIXES = [".linghun/logs", ".linghun/agent-runs", ".linghun/failures"];
67
78
  var SEARCH_EXCLUDED_FILE_SUFFIXES = [".tsbuildinfo"];
68
79
  var RG_TIMEOUT_MS = 3e4;
69
- function createToolContext(workspaceRoot = process.cwd()) {
80
+ function createToolContext(workspaceRoot = process.cwd(), options = {}) {
70
81
  return {
71
82
  workspaceRoot: resolve(workspaceRoot),
72
83
  changedFiles: [],
73
84
  todos: [],
74
85
  readSnapshots: {},
86
+ sourcePackCandidates: options.sourcePackCandidates,
75
87
  patchSummaries: {}
76
88
  };
77
89
  }
@@ -116,6 +128,52 @@ var toolDefinitions = {
116
128
  getToolUseSummary: (input) => `Read ${input.path}`,
117
129
  getActivityDescription: (input) => `Reading ${input.path}`
118
130
  }),
131
+ ReadSnippets: defineTool({
132
+ name: "ReadSnippets",
133
+ title: "\u8BFB\u53D6\u4EE3\u7801\u7247\u6BB5",
134
+ description: "\u4E00\u6B21\u8BFB\u53D6\u591A\u4E2A\u5DE5\u4F5C\u533A\u6587\u4EF6\u8303\u56F4\u3002",
135
+ permission: {
136
+ risk: "low",
137
+ scope: "workspace",
138
+ reason: "\u53EA\u8BFB\u67E5\u770B\u591A\u4E2A\u6587\u4EF6\u7247\u6BB5\u3002",
139
+ phase06Mode: "metadata-only"
140
+ },
141
+ isReadOnly: true,
142
+ isConcurrencySafe: true,
143
+ lifecycle: {
144
+ ...readOnlyLifecycle(),
145
+ maxResultSizeChars: MAX_READ_SNIPPET_OUTPUT_CHARS + 2e3
146
+ },
147
+ validateInput: validateReadSnippetsInput,
148
+ call: readSnippetsTool,
149
+ prompt: () => toolPrompts.ReadSnippets,
150
+ userFacingName: () => toolUserFacingNames.ReadSnippets,
151
+ getToolUseSummary: (input) => `ReadSnippets ${input.ranges.length} ranges`,
152
+ getActivityDescription: (input) => `Reading ${input.ranges.length} snippets`
153
+ }),
154
+ SourcePack: defineTool({
155
+ name: "SourcePack",
156
+ title: "\u5B9A\u4F4D\u4EE3\u7801\u7247\u6BB5",
157
+ description: "\u6309\u67E5\u8BE2\u5B9A\u4F4D\u5E76\u8FD4\u56DE\u5019\u9009\u4EE3\u7801\u7247\u6BB5\u3002",
158
+ permission: {
159
+ risk: "low",
160
+ scope: "workspace",
161
+ reason: "\u53EA\u8BFB\u641C\u7D22\u5E76\u8FD4\u56DE\u5019\u9009\u4EE3\u7801\u7247\u6BB5\u3002",
162
+ phase06Mode: "metadata-only"
163
+ },
164
+ isReadOnly: true,
165
+ isConcurrencySafe: true,
166
+ lifecycle: {
167
+ ...readOnlyLifecycle(),
168
+ maxResultSizeChars: MAX_READ_SNIPPET_OUTPUT_CHARS + 2e3
169
+ },
170
+ validateInput: validateSourcePackInput,
171
+ call: sourcePackTool,
172
+ prompt: () => toolPrompts.SourcePack,
173
+ userFacingName: () => toolUserFacingNames.SourcePack,
174
+ getToolUseSummary: (input) => `SourcePack ${input.query}`,
175
+ getActivityDescription: (input) => `Locating snippets for ${input.query}`
176
+ }),
119
177
  Write: defineTool({
120
178
  name: "Write",
121
179
  title: "\u5199\u5165\u6587\u4EF6",
@@ -420,6 +478,46 @@ function validateReadInput(input) {
420
478
  limit: readOptionalPositiveInteger(record, "limit", "Read")
421
479
  };
422
480
  }
481
+ function validateReadSnippetsInput(input) {
482
+ const record = validateRecord(input, "ReadSnippets");
483
+ const ranges = record.ranges;
484
+ if (!Array.isArray(ranges) || ranges.length === 0) {
485
+ throw new Error("ReadSnippets.ranges \u5FC5\u987B\u662F\u975E\u7A7A\u6570\u7EC4\u3002");
486
+ }
487
+ if (ranges.length > MAX_READ_SNIPPET_RANGES) {
488
+ throw new Error(`ReadSnippets.ranges \u6700\u591A ${MAX_READ_SNIPPET_RANGES} \u4E2A\u8303\u56F4\u3002`);
489
+ }
490
+ return {
491
+ ranges: ranges.map((item, index) => {
492
+ const range = validateRecord(item, "ReadSnippets");
493
+ const start = readPositiveLineNumber(range, "start", "ReadSnippets");
494
+ const end = readPositiveLineNumber(range, "end", "ReadSnippets");
495
+ if (end < start) {
496
+ throw new Error(`ReadSnippets.ranges[${index}].end \u5FC5\u987B\u5927\u4E8E\u7B49\u4E8E start\u3002`);
497
+ }
498
+ return {
499
+ path: readString(range, "path", "ReadSnippets"),
500
+ start,
501
+ end
502
+ };
503
+ })
504
+ };
505
+ }
506
+ function validateSourcePackInput(input) {
507
+ const record = validateRecord(input, "SourcePack");
508
+ const limit = readOptionalPositiveInteger(record, "limit", "SourcePack");
509
+ return {
510
+ query: readString(record, "query", "SourcePack"),
511
+ limit: limit === void 0 ? void 0 : Math.min(Math.max(limit, 1), SOURCE_PACK_MAX_LIMIT)
512
+ };
513
+ }
514
+ function readPositiveLineNumber(record, key, toolName) {
515
+ const value = record[key];
516
+ if (!Number.isInteger(value) || value < 1) {
517
+ throw new Error(`${toolName}.${key} \u5FC5\u987B\u662F 1-based \u6B63\u6574\u6570\u884C\u53F7\u3002`);
518
+ }
519
+ return value;
520
+ }
423
521
  function validateWriteInput(input) {
424
522
  const record = validateRecord(input, "Write");
425
523
  return {
@@ -566,6 +664,183 @@ async function readTool(input, context) {
566
664
  truncated
567
665
  };
568
666
  }
667
+ async function readSnippetsTool(input, context) {
668
+ const ranges = [];
669
+ let remainingChars = MAX_READ_SNIPPET_OUTPUT_CHARS;
670
+ let safetyTruncated = false;
671
+ for (const range of input.ranges) {
672
+ const requestedEnd = range.end;
673
+ const boundedEnd = Math.min(range.end, range.start + MAX_READ_SNIPPET_LINES - 1);
674
+ const rangeLineTruncated = boundedEnd < requestedEnd;
675
+ try {
676
+ const filePath = resolveWorkspacePath(context.workspaceRoot, range.path);
677
+ const content = await readFile(filePath, "utf8");
678
+ const info = await stat(filePath);
679
+ rememberReadSnapshot(context, filePath, content, info);
680
+ const lines = splitContentLines(content);
681
+ const selected = lines.slice(range.start - 1, boundedEnd);
682
+ const actualEnd = selected.length > 0 ? range.start + selected.length - 1 : range.start - 1;
683
+ const numbered = selected.map((line, index) => `${range.start + index} ${line}`).join("\n");
684
+ const capped = applySnippetSafetyCap(numbered, remainingChars);
685
+ remainingChars -= capped.usedChars;
686
+ safetyTruncated ||= capped.truncated;
687
+ ranges.push({
688
+ path: relativePath(context.workspaceRoot, filePath),
689
+ start: range.start,
690
+ end: actualEnd,
691
+ content: capped.content,
692
+ requestedStart: range.start,
693
+ requestedEnd,
694
+ totalLines: lines.length,
695
+ truncated: rangeLineTruncated || capped.truncated
696
+ });
697
+ if (capped.truncated) {
698
+ remainingChars = 0;
699
+ }
700
+ } catch (error) {
701
+ ranges.push({
702
+ path: range.path,
703
+ start: range.start,
704
+ end: boundedEnd,
705
+ content: "",
706
+ requestedStart: range.start,
707
+ requestedEnd,
708
+ truncated: rangeLineTruncated,
709
+ error: formatDiagnosticError(error)
710
+ });
711
+ }
712
+ }
713
+ const text = formatReadSnippetsOutput(ranges, safetyTruncated);
714
+ const okCount = ranges.filter((range) => !range.error).length;
715
+ return {
716
+ text,
717
+ summary: `ReadSnippets: ${okCount}/${ranges.length} ranges`,
718
+ data: {
719
+ ranges,
720
+ count: okCount,
721
+ requestedRanges: input.ranges.length,
722
+ safetyTruncated
723
+ },
724
+ truncated: ranges.some((range) => range.truncated) || safetyTruncated
725
+ };
726
+ }
727
+ function applySnippetSafetyCap(content, remainingChars) {
728
+ if (remainingChars <= 0) {
729
+ return {
730
+ content: "...\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\uFF0C\u540E\u7EED\u5185\u5BB9\u7701\u7565\uFF1B\u5982\u9700\u7CBE\u8BFB\u8BF7\u6307\u5B9A\u66F4\u5C0F\u8303\u56F4\u3002\uFF09",
731
+ usedChars: 0,
732
+ truncated: true
733
+ };
734
+ }
735
+ if (content.length <= remainingChars) {
736
+ return { content, usedChars: content.length, truncated: false };
737
+ }
738
+ const suffix = "\n...\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\uFF0C\u540E\u7EED\u5185\u5BB9\u7701\u7565\uFF1B\u5982\u9700\u7CBE\u8BFB\u8BF7\u6307\u5B9A\u66F4\u5C0F\u8303\u56F4\u3002\uFF09";
739
+ const sliceLength = Math.max(0, remainingChars - suffix.length);
740
+ return {
741
+ content: `${content.slice(0, sliceLength)}${suffix}`,
742
+ usedChars: remainingChars,
743
+ truncated: true
744
+ };
745
+ }
746
+ function formatReadSnippetsOutput(ranges, safetyTruncated) {
747
+ const lines = [];
748
+ for (const range of ranges) {
749
+ const header = `${range.path}:${range.start}-${range.end}`;
750
+ if (range.error) {
751
+ lines.push(`${header}
752
+ ERROR: ${range.error}`);
753
+ continue;
754
+ }
755
+ lines.push(`${header}
756
+ ${range.content}`);
757
+ if (range.truncated) {
758
+ lines.push("...\uFF08\u8BE5\u8303\u56F4\u5DF2\u622A\u65AD\uFF1B\u53EF\u7EE7\u7EED\u8BFB\u53D6\u540E\u7EED\u8303\u56F4\u3002\uFF09");
759
+ }
760
+ }
761
+ if (safetyTruncated) {
762
+ lines.push("...\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\uFF0C\u540E\u7EED\u5185\u5BB9\u7701\u7565\uFF1B\u5982\u9700\u7CBE\u8BFB\u8BF7\u6307\u5B9A\u66F4\u5C0F\u8303\u56F4\u3002\uFF09");
763
+ }
764
+ return lines.join("\n\n");
765
+ }
766
+ async function sourcePackTool(input, context) {
767
+ const limit = input.limit ?? SOURCE_PACK_DEFAULT_LIMIT;
768
+ const terms = extractSourcePackTerms(input.query);
769
+ if (terms.length === 0) {
770
+ return {
771
+ text: "empty: query did not contain searchable terms.",
772
+ summary: "SourcePack: 0 snippets",
773
+ data: { query: input.query, snippets: [], count: 0, empty: true }
774
+ };
775
+ }
776
+ const matchResult = await findSourcePackMatches(input.query, terms, context, limit * 4);
777
+ const snippets = [];
778
+ const seen = /* @__PURE__ */ new Set();
779
+ let remainingChars = MAX_READ_SNIPPET_OUTPUT_CHARS;
780
+ let safetyTruncated = false;
781
+ for (const match of matchResult.matches) {
782
+ if (snippets.length >= limit) break;
783
+ const start = match.start ?? Math.max(1, match.line - SOURCE_PACK_CONTEXT_LINES);
784
+ const end = match.end ?? match.line + SOURCE_PACK_CONTEXT_LINES;
785
+ const key = `${match.path}:${start}:${end}`;
786
+ if (seen.has(key)) continue;
787
+ seen.add(key);
788
+ try {
789
+ const filePath = resolveWorkspacePath(context.workspaceRoot, match.path);
790
+ const content = await readFile(filePath, "utf8");
791
+ const info = await stat(filePath);
792
+ rememberReadSnapshot(context, filePath, content, info);
793
+ const lines = splitContentLines(content);
794
+ const boundedEnd = Math.min(end, lines.length);
795
+ const selected = lines.slice(start - 1, boundedEnd);
796
+ const numbered = selected.map((line, index) => `${start + index} ${line}`).join("\n");
797
+ const capped = applySnippetSafetyCap(numbered, remainingChars);
798
+ remainingChars -= capped.usedChars;
799
+ safetyTruncated ||= capped.truncated;
800
+ snippets.push({
801
+ path: relativePath(context.workspaceRoot, filePath),
802
+ start,
803
+ end: boundedEnd,
804
+ content: capped.content,
805
+ requestedStart: start,
806
+ requestedEnd: end,
807
+ totalLines: lines.length,
808
+ truncated: capped.truncated,
809
+ reason: match.reason ?? `matched "${match.term}" at line ${match.line}`,
810
+ confidence: estimateSourcePackConfidence(input.query, match),
811
+ source: match.source
812
+ });
813
+ if (capped.truncated) {
814
+ break;
815
+ }
816
+ } catch {
817
+ continue;
818
+ }
819
+ }
820
+ if (snippets.length === 0) {
821
+ return {
822
+ text: "empty: no matching source snippets found.",
823
+ summary: "SourcePack: 0 snippets",
824
+ data: { query: input.query, snippets: [], count: 0, empty: true }
825
+ };
826
+ }
827
+ const text = formatSourcePackOutput(snippets, safetyTruncated);
828
+ return {
829
+ text,
830
+ summary: `SourcePack: ${snippets.length} snippets`,
831
+ data: {
832
+ query: input.query,
833
+ snippets,
834
+ count: snippets.length,
835
+ searchedTerms: terms,
836
+ source: matchResult.source,
837
+ fallback: matchResult.source !== "index",
838
+ candidatePaths: unique(snippets.map((snippet) => snippet.path)),
839
+ safetyTruncated
840
+ },
841
+ truncated: safetyTruncated || snippets.some((snippet) => snippet.truncated)
842
+ };
843
+ }
569
844
  function splitContentLines(content) {
570
845
  if (content.length === 0) {
571
846
  return [];
@@ -744,7 +1019,8 @@ async function bashTool(input, context) {
744
1019
  context.workspaceRoot,
745
1020
  timeoutMs,
746
1021
  context.abortSignal,
747
- (stream, text) => void context.onProgress?.({ toolName: "Bash", stream, text })
1022
+ (stream, text) => void context.onProgress?.({ toolName: "Bash", stream, text }),
1023
+ context.trackChildProcess
748
1024
  );
749
1025
  const adapterLines = adapted.command === input.command && adapted.adapter === "native" ? [] : [
750
1026
  `adapter ${adapted.adapter}`,
@@ -763,13 +1039,28 @@ async function bashTool(input, context) {
763
1039
  const truncated = fullText.length > BASH_PREVIEW_LIMIT;
764
1040
  const preview = truncated ? `${fullText.slice(0, BASH_PREVIEW_LIMIT)}
765
1041
  ...\uFF08\u8F93\u51FA\u5DF2\u622A\u65AD\uFF0C\u5B8C\u6574\u65E5\u5FD7\u89C1 fullOutputPath\uFF09` : fullText;
1042
+ const details = createBashDetails(fullOutputPath, fullText);
766
1043
  return {
767
1044
  text: preview,
1045
+ details,
768
1046
  data: adapted.adapter === "native" ? { exitCode: result.exitCode, outcome: result.outcome } : { exitCode: result.exitCode, outcome: result.outcome, adapter: adapted.adapter },
769
1047
  truncated,
770
1048
  fullOutputPath
771
1049
  };
772
1050
  }
1051
+ function createBashDetails(fullOutputPath, fullText) {
1052
+ return [
1053
+ `fullOutputPath: ${fullOutputPath}`,
1054
+ "--- summary",
1055
+ ...fullText.split(/\r?\n/u).slice(0, 8),
1056
+ "--- tail",
1057
+ ...tailLines(fullText, 80)
1058
+ ].join("\n");
1059
+ }
1060
+ function tailLines(text, limit) {
1061
+ const lines = text.split(/\r?\n/u);
1062
+ return lines.slice(Math.max(0, lines.length - limit));
1063
+ }
773
1064
  function adaptShellCommand(command) {
774
1065
  return adaptShellCommandForPlatform(command, process.platform);
775
1066
  }
@@ -1391,6 +1682,149 @@ async function tryRipgrepFiles(input, context, root, limit) {
1391
1682
  if (!result) return null;
1392
1683
  return { matches: result.lines.slice(0, limit), truncated: result.truncated };
1393
1684
  }
1685
+ async function findSourcePackMatches(query, terms, context, limit) {
1686
+ const indexMatches = sourcePackMatchesFromCandidates(query, context.sourcePackCandidates, limit);
1687
+ if (indexMatches.length > 0) {
1688
+ return { source: "index", matches: indexMatches };
1689
+ }
1690
+ const rgMatches = await tryRipgrepSourcePack(terms, context, limit);
1691
+ if (rgMatches && rgMatches.length > 0) {
1692
+ return { source: "rg", matches: rgMatches };
1693
+ }
1694
+ const matches = [];
1695
+ for await (const filePath of listFiles(context.workspaceRoot, () => matches.length >= limit)) {
1696
+ const content = await safeReadText(filePath, context);
1697
+ if (content === null) continue;
1698
+ const rel = relativePath(context.workspaceRoot, filePath);
1699
+ const pathTerm = terms.find((item) => rel.toLowerCase().includes(item.toLowerCase()));
1700
+ if (pathTerm) {
1701
+ matches.push({
1702
+ path: rel,
1703
+ line: 1,
1704
+ text: rel,
1705
+ term: pathTerm,
1706
+ source: "file_name",
1707
+ confidence: 0.35,
1708
+ reason: `fallback file name matched "${pathTerm}"`
1709
+ });
1710
+ if (matches.length >= limit) break;
1711
+ }
1712
+ const lines = content.split(/\r?\n/u);
1713
+ for (const [index, line] of lines.entries()) {
1714
+ const lower = line.toLowerCase();
1715
+ const term = terms.find((item) => lower.includes(item.toLowerCase()));
1716
+ if (!term) continue;
1717
+ matches.push({
1718
+ path: rel,
1719
+ line: index + 1,
1720
+ text: line,
1721
+ term,
1722
+ source: "local_scan",
1723
+ confidence: 0.4,
1724
+ reason: `fallback local scan matched "${term}" at line ${index + 1}`
1725
+ });
1726
+ if (matches.length >= limit) break;
1727
+ }
1728
+ }
1729
+ return { source: matches[0]?.source ?? "local_scan", matches };
1730
+ }
1731
+ async function tryRipgrepSourcePack(terms, context, limit) {
1732
+ const args = [
1733
+ "--line-number",
1734
+ "--no-heading",
1735
+ "--color",
1736
+ "never",
1737
+ "--hidden",
1738
+ "--no-ignore",
1739
+ "--max-columns",
1740
+ "500",
1741
+ "-i",
1742
+ "-F",
1743
+ ...createRgExcludeArgs(context.workspaceRoot, context.workspaceRoot)
1744
+ ];
1745
+ for (const term of terms) {
1746
+ args.push("-e", term);
1747
+ }
1748
+ args.push(".");
1749
+ const result = await runRipgrep(
1750
+ args,
1751
+ context,
1752
+ limit,
1753
+ (line) => normalizeRgGrepLine(line, context.workspaceRoot)
1754
+ );
1755
+ if (!result) return null;
1756
+ return result.lines.flatMap((line) => parseSourcePackRgLine(line, terms));
1757
+ }
1758
+ function parseSourcePackRgLine(line, terms) {
1759
+ const firstColon = line.indexOf(":");
1760
+ const secondColon = firstColon < 0 ? -1 : line.indexOf(":", firstColon + 1);
1761
+ if (firstColon < 0 || secondColon < 0) return [];
1762
+ const lineNumber = Number.parseInt(line.slice(firstColon + 1, secondColon), 10);
1763
+ if (!Number.isInteger(lineNumber)) return [];
1764
+ const text = line.slice(secondColon + 1).trim();
1765
+ const lower = text.toLowerCase();
1766
+ const term = terms.find((item) => lower.includes(item.toLowerCase())) ?? terms[0];
1767
+ return [
1768
+ {
1769
+ path: line.slice(0, firstColon),
1770
+ line: lineNumber,
1771
+ text,
1772
+ term,
1773
+ source: "rg",
1774
+ confidence: 0.6,
1775
+ reason: `rg matched "${term}" at line ${lineNumber}`
1776
+ }
1777
+ ];
1778
+ }
1779
+ function sourcePackMatchesFromCandidates(query, candidates, limit) {
1780
+ if (!candidates || candidates.length === 0) return [];
1781
+ const terms = extractSourcePackTerms(query);
1782
+ return candidates.slice(0, limit).map((candidate) => {
1783
+ const start = Math.max(1, candidate.start);
1784
+ const end = Math.max(start, candidate.end);
1785
+ const term = terms[0] ?? query;
1786
+ return {
1787
+ path: candidate.path,
1788
+ line: start,
1789
+ text: candidate.reason ?? candidate.path,
1790
+ term,
1791
+ source: "index",
1792
+ start,
1793
+ end,
1794
+ confidence: candidate.confidence ?? 0.85,
1795
+ reason: candidate.reason ?? `index candidate for "${query}"`
1796
+ };
1797
+ });
1798
+ }
1799
+ function extractSourcePackTerms(query) {
1800
+ const terms = query.split(/[^\p{L}\p{N}_.$/@-]+/u).map((term) => term.trim()).filter((term) => term.length >= 2 && !/^\d+$/u.test(term));
1801
+ return unique(terms).slice(0, SOURCE_PACK_MAX_TERMS);
1802
+ }
1803
+ function estimateSourcePackConfidence(query, match) {
1804
+ if (match.confidence !== void 0) return match.confidence;
1805
+ const queryTerms = extractSourcePackTerms(query);
1806
+ const haystack = `${match.path} ${match.text}`.toLowerCase();
1807
+ const hitCount = queryTerms.filter((term) => haystack.includes(term.toLowerCase())).length;
1808
+ const base = match.source === "index" ? 0.7 : match.source === "rg" ? 0.45 : 0.25;
1809
+ const cap = match.source === "index" ? 0.95 : match.source === "rg" ? 0.75 : 0.55;
1810
+ return Math.min(cap, base + hitCount * 0.15);
1811
+ }
1812
+ function formatSourcePackOutput(snippets, safetyTruncated) {
1813
+ const lines = [];
1814
+ for (const snippet of snippets) {
1815
+ lines.push(
1816
+ [
1817
+ `${snippet.path}:${snippet.start}-${snippet.end}`,
1818
+ `source: ${snippet.source}; reason: ${snippet.reason}; confidence: ${snippet.confidence.toFixed(2)}`,
1819
+ snippet.content
1820
+ ].join("\n")
1821
+ );
1822
+ }
1823
+ if (safetyTruncated) {
1824
+ lines.push("...\uFF08\u7ED3\u679C\u5DF2\u622A\u65AD\uFF0C\u540E\u7EED\u5185\u5BB9\u7701\u7565\uFF1B\u5982\u9700\u7CBE\u8BFB\u8BF7\u6307\u5B9A\u66F4\u5C0F\u8303\u56F4\u3002\uFF09");
1825
+ }
1826
+ return lines.join("\n\n");
1827
+ }
1394
1828
  function createRgExcludeArgs(root, workspaceRoot) {
1395
1829
  const searchRootRel = stripCurrentDirectoryPrefix(
1396
1830
  relative(workspaceRoot, root).replaceAll("\\", "/")
@@ -1512,9 +1946,16 @@ function globToRegExp(pattern) {
1512
1946
  }
1513
1947
  return new RegExp(result);
1514
1948
  }
1515
- function runShell(command, cwd, timeoutMs, signal, onProgress) {
1949
+ function runShell(command, cwd, timeoutMs, signal, onProgress, trackChildProcess) {
1516
1950
  return new Promise((resolvePromise) => {
1517
- const child = spawn(command, { cwd, shell: true, windowsHide: true });
1951
+ const detached = process.platform !== "win32";
1952
+ const child = spawn(command, { cwd, shell: true, windowsHide: true, detached });
1953
+ trackChildProcess?.(child, {
1954
+ detached,
1955
+ cwd,
1956
+ label: `Bash:${command.slice(0, 80)}`,
1957
+ retainAfterExit: detached
1958
+ });
1518
1959
  let output = "";
1519
1960
  let settled = false;
1520
1961
  let forcedKillTimer;
@@ -1544,7 +1985,16 @@ function runShell(command, cwd, timeoutMs, signal, onProgress) {
1544
1985
  await stopWindowsProcessTree(child.pid, cwd);
1545
1986
  return;
1546
1987
  }
1547
- child.kill(force ? "SIGKILL" : "SIGTERM");
1988
+ const signalName = force ? "SIGKILL" : "SIGTERM";
1989
+ if (detached && child.pid) {
1990
+ try {
1991
+ process.kill(-child.pid, signalName);
1992
+ } catch {
1993
+ child.kill(signalName);
1994
+ }
1995
+ } else {
1996
+ child.kill(signalName);
1997
+ }
1548
1998
  if (force) {
1549
1999
  await waitForChildClose();
1550
2000
  }
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  ReadTool
3
- } from "../../chunk-RBHQ5WNR.js";
4
- import "../../chunk-HNIVNZIS.js";
3
+ } from "../../chunk-TZ6QK52L.js";
5
4
  import "../../chunk-K3YDFDLP.js";
5
+ import "../../chunk-HNIVNZIS.js";
6
6
  export {
7
7
  ReadTool
8
8
  };
@@ -0,0 +1,6 @@
1
+ export declare const ReadSnippetsTool: {
2
+ readonly name: "ReadSnippets";
3
+ readonly prompt: "Use ReadSnippets to read multiple known file line ranges in one call. Prefer it after search, index, or codebase-memory hits return path/range candidates.";
4
+ readonly userFacingName: "读取代码片段";
5
+ };
6
+ //# sourceMappingURL=ReadSnippetsTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ReadSnippetsTool.d.ts","sourceRoot":"","sources":["../../../src/tools/ReadSnippets/ReadSnippetsTool.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,gBAAgB;;;;CAA4D,CAAC"}
@@ -0,0 +1,7 @@
1
+ import {
2
+ ReadSnippetsTool
3
+ } from "../../chunk-GI5XI4HN.js";
4
+ import "../../chunk-WEWXKRKL.js";
5
+ export {
6
+ ReadSnippetsTool
7
+ };
@@ -0,0 +1,2 @@
1
+ export declare const prompt = "Use ReadSnippets to read multiple known file line ranges in one call. Prefer it after search, index, or codebase-memory hits return path/range candidates.";
2
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/tools/ReadSnippets/prompt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,+JAC2I,CAAC"}
@@ -0,0 +1,6 @@
1
+ import {
2
+ prompt
3
+ } from "../../chunk-WEWXKRKL.js";
4
+ export {
5
+ prompt
6
+ };
@@ -0,0 +1,6 @@
1
+ export declare const SourcePackTool: {
2
+ readonly name: "SourcePack";
3
+ readonly prompt: "Use SourcePack to locate a small evidence pack of candidate source snippets for a query. If index/codebase-memory already returned paths or ranges, call ReadSnippets on those candidates first.";
4
+ readonly userFacingName: "定位代码片段";
5
+ };
6
+ //# sourceMappingURL=SourcePackTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SourcePackTool.d.ts","sourceRoot":"","sources":["../../../src/tools/SourcePack/SourcePackTool.ts"],"names":[],"mappings":"AAIA,eAAO,MAAM,cAAc;;;;CAA0D,CAAC"}
@@ -0,0 +1,7 @@
1
+ import {
2
+ SourcePackTool
3
+ } from "../../chunk-A6FUAM64.js";
4
+ import "../../chunk-YCO6C7KF.js";
5
+ export {
6
+ SourcePackTool
7
+ };
@@ -0,0 +1,2 @@
1
+ export declare const prompt = "Use SourcePack to locate a small evidence pack of candidate source snippets for a query. If index/codebase-memory already returned paths or ranges, call ReadSnippets on those candidates first.";
2
+ //# sourceMappingURL=prompt.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../../src/tools/SourcePack/prompt.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,MAAM,qMACiL,CAAC"}
@@ -0,0 +1,6 @@
1
+ import {
2
+ prompt
3
+ } from "../../chunk-YCO6C7KF.js";
4
+ export {
5
+ prompt
6
+ };
@@ -1,8 +1,8 @@
1
1
  import {
2
2
  TodoTool
3
- } from "../../chunk-4567YAXM.js";
4
- import "../../chunk-XZWSO5CM.js";
3
+ } from "../../chunk-MFHY7PBM.js";
5
4
  import "../../chunk-SZFZPQGL.js";
5
+ import "../../chunk-XZWSO5CM.js";
6
6
  export {
7
7
  TodoTool
8
8
  };
@@ -1 +1 @@
1
- {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/tools/prompts.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAYhD,CAAC"}
1
+ {"version":3,"file":"prompts.d.ts","sourceRoot":"","sources":["../../src/tools/prompts.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,WAAW,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAchD,CAAC"}
@@ -1,27 +1,31 @@
1
1
  import {
2
2
  toolPrompts
3
- } from "../chunk-KGDJAST5.js";
4
- import "../chunk-4EZHIDZ6.js";
5
- import "../chunk-YR4HWOR2.js";
6
- import "../chunk-VAFW24RN.js";
3
+ } from "../chunk-DWXJBDPQ.js";
7
4
  import "../chunk-I3Z4OKMS.js";
8
5
  import "../chunk-PS2ZOFZ6.js";
9
6
  import "../chunk-NPKLGVDQ.js";
10
- import "../chunk-VJDLOFCF.js";
11
- import "../chunk-3RP665TH.js";
12
- import "../chunk-IOC3BSPT.js";
13
7
  import "../chunk-LGZOG7IQ.js";
14
8
  import "../chunk-ZYAEUABC.js";
15
9
  import "../chunk-SWK6XRZQ.js";
10
+ import "../chunk-4EZHIDZ6.js";
11
+ import "../chunk-YR4HWOR2.js";
12
+ import "../chunk-VAFW24RN.js";
13
+ import "../chunk-GI5XI4HN.js";
14
+ import "../chunk-WEWXKRKL.js";
15
+ import "../chunk-A6FUAM64.js";
16
+ import "../chunk-YCO6C7KF.js";
17
+ import "../chunk-MFHY7PBM.js";
18
+ import "../chunk-SZFZPQGL.js";
19
+ import "../chunk-XZWSO5CM.js";
16
20
  import "../chunk-AZCQL24J.js";
17
21
  import "../chunk-HUIZOB4A.js";
18
22
  import "../chunk-MK3YP2VR.js";
19
- import "../chunk-RBHQ5WNR.js";
20
- import "../chunk-HNIVNZIS.js";
23
+ import "../chunk-VJDLOFCF.js";
24
+ import "../chunk-3RP665TH.js";
25
+ import "../chunk-IOC3BSPT.js";
26
+ import "../chunk-TZ6QK52L.js";
21
27
  import "../chunk-K3YDFDLP.js";
22
- import "../chunk-4567YAXM.js";
23
- import "../chunk-XZWSO5CM.js";
24
- import "../chunk-SZFZPQGL.js";
28
+ import "../chunk-HNIVNZIS.js";
25
29
  import "../chunk-DN3KJZRV.js";
26
30
  import "../chunk-2U4BZXAI.js";
27
31
  import "../chunk-ITBZHMZQ.js";
@@ -1 +1 @@
1
- {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/tools/ui.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAYxD,CAAC"}
1
+ {"version":3,"file":"ui.d.ts","sourceRoot":"","sources":["../../src/tools/ui.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,eAAO,MAAM,mBAAmB,EAAE,MAAM,CAAC,QAAQ,EAAE,MAAM,CAcxD,CAAC"}
package/dist/tools/ui.js CHANGED
@@ -1,27 +1,31 @@
1
1
  import {
2
2
  toolUserFacingNames
3
- } from "../chunk-NKWRH36V.js";
4
- import "../chunk-4EZHIDZ6.js";
5
- import "../chunk-YR4HWOR2.js";
6
- import "../chunk-VAFW24RN.js";
3
+ } from "../chunk-2R75FXZG.js";
7
4
  import "../chunk-I3Z4OKMS.js";
8
5
  import "../chunk-PS2ZOFZ6.js";
9
6
  import "../chunk-NPKLGVDQ.js";
10
- import "../chunk-VJDLOFCF.js";
11
- import "../chunk-3RP665TH.js";
12
- import "../chunk-IOC3BSPT.js";
13
7
  import "../chunk-LGZOG7IQ.js";
14
8
  import "../chunk-ZYAEUABC.js";
15
9
  import "../chunk-SWK6XRZQ.js";
10
+ import "../chunk-4EZHIDZ6.js";
11
+ import "../chunk-YR4HWOR2.js";
12
+ import "../chunk-VAFW24RN.js";
13
+ import "../chunk-GI5XI4HN.js";
14
+ import "../chunk-WEWXKRKL.js";
15
+ import "../chunk-A6FUAM64.js";
16
+ import "../chunk-YCO6C7KF.js";
17
+ import "../chunk-MFHY7PBM.js";
18
+ import "../chunk-SZFZPQGL.js";
19
+ import "../chunk-XZWSO5CM.js";
16
20
  import "../chunk-AZCQL24J.js";
17
21
  import "../chunk-HUIZOB4A.js";
18
22
  import "../chunk-MK3YP2VR.js";
19
- import "../chunk-RBHQ5WNR.js";
20
- import "../chunk-HNIVNZIS.js";
23
+ import "../chunk-VJDLOFCF.js";
24
+ import "../chunk-3RP665TH.js";
25
+ import "../chunk-IOC3BSPT.js";
26
+ import "../chunk-TZ6QK52L.js";
21
27
  import "../chunk-K3YDFDLP.js";
22
- import "../chunk-4567YAXM.js";
23
- import "../chunk-XZWSO5CM.js";
24
- import "../chunk-SZFZPQGL.js";
28
+ import "../chunk-HNIVNZIS.js";
25
29
  import "../chunk-DN3KJZRV.js";
26
30
  import "../chunk-2U4BZXAI.js";
27
31
  import "../chunk-ITBZHMZQ.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@linghun/tools",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "license": "Apache-2.0",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
@@ -1,9 +1,9 @@
1
- import {
2
- userFacingName
3
- } from "./chunk-XZWSO5CM.js";
4
1
  import {
5
2
  prompt
6
3
  } from "./chunk-SZFZPQGL.js";
4
+ import {
5
+ userFacingName
6
+ } from "./chunk-XZWSO5CM.js";
7
7
 
8
8
  // src/tools/Todo/TodoTool.ts
9
9
  var TodoTool = { name: "Todo", prompt, userFacingName };
@@ -1,9 +1,9 @@
1
- import {
2
- prompt
3
- } from "./chunk-HNIVNZIS.js";
4
1
  import {
5
2
  userFacingName
6
3
  } from "./chunk-K3YDFDLP.js";
4
+ import {
5
+ prompt
6
+ } from "./chunk-HNIVNZIS.js";
7
7
 
8
8
  // src/tools/Read/ReadTool.ts
9
9
  var ReadTool = { name: "Read", prompt, userFacingName };