Skip to content

Commit 197676e

Browse files
committed
refactor(session): 提取并迁移会话相关工具函数
- 将会话相关的工具函数从 session/index.ts 中移除 - 在 session/utils.ts 中重新实现并导出这些工具函数 - 调整了导入路径,改用新的工具函数模块 - 修正了多个文件中对 executeValidatedTool 的导入路径 - 统一了 SkillsDropdown 组件中的 DropdownMenu 导入名称
1 parent 0a1a405 commit 197676e

7 files changed

Lines changed: 83 additions & 78 deletions

File tree

src/session/index.ts

Lines changed: 9 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ import * as fs from "fs";
22
import * as path from "path";
33
import * as os from "os";
44
import * as crypto from "crypto";
5-
import { fileURLToPath } from "url";
65
import matter from "gray-matter";
76
import ejs from "ejs";
87
import type { ChatCompletionContentPart, ChatCompletionMessageParam } from "openai/resources/chat/completions";
@@ -44,7 +43,15 @@ import {
4443
type UserToolPermission,
4544
} from "../common/permissions";
4645

47-
import { getCompactPromptTokenThreshold, getTotalTokens } from "./utils";
46+
import {
47+
accumulateUsage,
48+
accumulateUsagePerModel,
49+
getCompactPromptTokenThreshold,
50+
getExtensionRoot,
51+
getTotalTokens,
52+
isUsageRecord,
53+
summarizeCompletionOptions,
54+
} from "./utils";
4855
import {
4956
type BashTimeoutAdjustment,
5057
type LlmStreamProgress,
@@ -72,76 +79,6 @@ type ChatCompletionDebugOptions = {
7279
params?: Record<string, unknown>;
7380
};
7481

75-
function isUsageRecord(value: unknown): value is Record<string, unknown> {
76-
return value !== null && typeof value === "object" && !Array.isArray(value);
77-
}
78-
79-
function summarizeCompletionOptions(options?: Record<string, unknown>): Record<string, unknown> | undefined {
80-
if (!options) {
81-
return undefined;
82-
}
83-
return {
84-
...options,
85-
signal: options.signal instanceof AbortSignal ? { aborted: options.signal.aborted } : options.signal,
86-
};
87-
}
88-
89-
function addUsageValue(current: unknown, next: unknown): unknown {
90-
if (typeof next === "number") {
91-
return (typeof current === "number" ? current : 0) + next;
92-
}
93-
94-
if (isUsageRecord(next)) {
95-
const currentRecord = isUsageRecord(current) ? current : {};
96-
const result: Record<string, unknown> = { ...currentRecord };
97-
for (const [key, value] of Object.entries(next)) {
98-
result[key] = addUsageValue(currentRecord[key], value);
99-
}
100-
return result;
101-
}
102-
103-
return next;
104-
}
105-
106-
function accumulateUsage(current: ModelUsage | null, next: unknown | null | undefined): ModelUsage | null {
107-
if (next == null) {
108-
return current ?? null;
109-
}
110-
return addUsageValue(current, next) as ModelUsage;
111-
}
112-
113-
function usageWithRequestCount(usage: ModelUsage): ModelUsage {
114-
const totalReqs = typeof usage.total_reqs === "number" ? usage.total_reqs + 1 : 1;
115-
return {
116-
...usage,
117-
total_reqs: totalReqs,
118-
};
119-
}
120-
121-
function accumulateUsagePerModel(
122-
current: Record<string, ModelUsage> | null | undefined,
123-
model: string,
124-
next: ModelUsage | null | undefined
125-
): Record<string, ModelUsage> | null {
126-
if (next == null) {
127-
return current ?? null;
128-
}
129-
130-
const usagePerModel = { ...(current ?? {}) };
131-
const modelName = model.trim() || "unknown";
132-
usagePerModel[modelName] = accumulateUsage(usagePerModel[modelName] ?? null, usageWithRequestCount(next))!;
133-
return usagePerModel;
134-
}
135-
136-
function getExtensionRoot(): string {
137-
if (typeof __dirname !== "undefined") {
138-
return path.resolve(__dirname, "../..");
139-
}
140-
141-
const currentFilePath = fileURLToPath(import.meta.url);
142-
return path.resolve(path.dirname(currentFilePath), "../..");
143-
}
144-
14582
export class SessionManager {
14683
private readonly projectRoot: string;
14784
private readonly createOpenAIClient: CreateOpenAIClient;

src/session/utils.ts

Lines changed: 69 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import * as path from "path";
2+
import { fileURLToPath } from "url";
13
import { DEEPSEEK_V4_MODELS } from "../common/model-capabilities";
24
import type { ModelUsage } from "./types";
35

@@ -10,7 +12,7 @@ export function getCompactPromptTokenThreshold(model: string): number {
1012
: DEFAULT_COMPACT_PROMPT_TOKEN_THRESHOLD;
1113
}
1214

13-
function isUsageRecord(value: unknown): value is Record<string, unknown> {
15+
export function isUsageRecord(value: unknown): value is Record<string, unknown> {
1416
return value !== null && typeof value === "object" && !Array.isArray(value);
1517
}
1618

@@ -21,3 +23,69 @@ export function getTotalTokens(usage: ModelUsage | null | undefined): number {
2123
const totalTokens = (usage as Record<string, unknown>).total_tokens;
2224
return typeof totalTokens === "number" ? totalTokens : 0;
2325
}
26+
27+
export function summarizeCompletionOptions(options?: Record<string, unknown>): Record<string, unknown> | undefined {
28+
if (!options) {
29+
return undefined;
30+
}
31+
return {
32+
...options,
33+
signal: options.signal instanceof AbortSignal ? { aborted: options.signal.aborted } : options.signal,
34+
};
35+
}
36+
37+
export function addUsageValue(current: unknown, next: unknown): unknown {
38+
if (typeof next === "number") {
39+
return (typeof current === "number" ? current : 0) + next;
40+
}
41+
42+
if (isUsageRecord(next)) {
43+
const currentRecord = isUsageRecord(current) ? current : {};
44+
const result: Record<string, unknown> = { ...currentRecord };
45+
for (const [key, value] of Object.entries(next)) {
46+
result[key] = addUsageValue(currentRecord[key], value);
47+
}
48+
return result;
49+
}
50+
51+
return next;
52+
}
53+
54+
export function accumulateUsage(current: ModelUsage | null, next: unknown | null | undefined): ModelUsage | null {
55+
if (next == null) {
56+
return current ?? null;
57+
}
58+
return addUsageValue(current, next) as ModelUsage;
59+
}
60+
61+
export function usageWithRequestCount(usage: ModelUsage): ModelUsage {
62+
const totalReqs = typeof usage.total_reqs === "number" ? usage.total_reqs + 1 : 1;
63+
return {
64+
...usage,
65+
total_reqs: totalReqs,
66+
};
67+
}
68+
69+
export function accumulateUsagePerModel(
70+
current: Record<string, ModelUsage> | null | undefined,
71+
model: string,
72+
next: ModelUsage | null | undefined
73+
): Record<string, ModelUsage> | null {
74+
if (next == null) {
75+
return current ?? null;
76+
}
77+
78+
const usagePerModel = { ...(current ?? {}) };
79+
const modelName = model.trim() || "unknown";
80+
usagePerModel[modelName] = accumulateUsage(usagePerModel[modelName] ?? null, usageWithRequestCount(next))!;
81+
return usagePerModel;
82+
}
83+
84+
export function getExtensionRoot(): string {
85+
if (typeof __dirname !== "undefined") {
86+
return path.resolve(__dirname, "../..");
87+
}
88+
89+
const currentFilePath = fileURLToPath(import.meta.url);
90+
return path.resolve(path.dirname(currentFilePath), "../..");
91+
}

src/tools/edit-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
readTextFileWithMetadata,
99
writeTextFile,
1010
} from "../common/file-utils";
11-
import { executeValidatedTool, semanticBoolean } from "../common/runtime/runtime";
11+
import { executeValidatedTool, semanticBoolean } from "../common/runtime/validate";
1212
import {
1313
createSnippet,
1414
getFileState,

src/tools/update-plan-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { z } from "zod";
22
import type { ToolExecutionContext, ToolExecutionResult } from "./executor";
3-
import { executeValidatedTool } from "../common/runtime/runtime";
3+
import { executeValidatedTool } from "../common/runtime/validate";
44

55
const updatePlanSchema = z.strictObject({
66
plan: z.string().trim().min(1, "plan must not be empty."),

src/tools/write-handler.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import {
99
readTextFileWithMetadata,
1010
writeTextFile,
1111
} from "../common/file-utils";
12-
import { executeValidatedTool } from "../common/runtime/runtime";
12+
import { executeValidatedTool } from "../common/runtime/validate";
1313
import {
1414
getFileState,
1515
isAbsoluteFilePath,

src/ui/components/SkillsDropdown/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Index from "../DropdownMenu";
1+
import DropdownMenu from "../DropdownMenu";
22
import React, { useEffect, useState } from "react";
33
import type { SkillInfo } from "../../../session/types";
44
import { useInput } from "ink";
@@ -52,7 +52,7 @@ const SkillsDropdown: React.FC<{
5252
}
5353

5454
return (
55-
<Index
55+
<DropdownMenu
5656
width={width}
5757
title="Select Skills"
5858
helpText="Space toggle · Enter toggle · Esc to close"

0 commit comments

Comments
 (0)