hcent 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/LICENSE +21 -0
- package/README.md +160 -0
- package/dist/agent/context-manager.d.ts +14 -0
- package/dist/agent/context-manager.js +109 -0
- package/dist/agent/context-manager.js.map +1 -0
- package/dist/agent/index.d.ts +27 -0
- package/dist/agent/index.js +120 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/bin.d.ts +2 -0
- package/dist/bin.js +40 -0
- package/dist/bin.js.map +1 -0
- package/dist/config/index.d.ts +25 -0
- package/dist/config/index.js +109 -0
- package/dist/config/index.js.map +1 -0
- package/dist/main.d.ts +1 -0
- package/dist/main.js +43 -0
- package/dist/main.js.map +1 -0
- package/dist/provider/index.d.ts +23 -0
- package/dist/provider/index.js +124 -0
- package/dist/provider/index.js.map +1 -0
- package/dist/provider/provider-manager.d.ts +9 -0
- package/dist/provider/provider-manager.js +43 -0
- package/dist/provider/provider-manager.js.map +1 -0
- package/dist/session/index.d.ts +39 -0
- package/dist/session/index.js +69 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/session-store.d.ts +19 -0
- package/dist/session/session-store.js +109 -0
- package/dist/session/session-store.js.map +1 -0
- package/dist/setup/index.d.ts +11 -0
- package/dist/setup/index.js +97 -0
- package/dist/setup/index.js.map +1 -0
- package/dist/skill/command-palette.d.ts +12 -0
- package/dist/skill/command-palette.js +62 -0
- package/dist/skill/command-palette.js.map +1 -0
- package/dist/skill/index.d.ts +15 -0
- package/dist/skill/index.js +145 -0
- package/dist/skill/index.js.map +1 -0
- package/dist/skill/skill-pointer.d.ts +18 -0
- package/dist/skill/skill-pointer.js +70 -0
- package/dist/skill/skill-pointer.js.map +1 -0
- package/dist/tools/index.d.ts +26 -0
- package/dist/tools/index.js +745 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/permission.d.ts +11 -0
- package/dist/tools/permission.js +11 -0
- package/dist/tools/permission.js.map +1 -0
- package/dist/tui/aligned-text.d.ts +14 -0
- package/dist/tui/aligned-text.js +46 -0
- package/dist/tui/aligned-text.js.map +1 -0
- package/dist/tui/builtin-commands.d.ts +40 -0
- package/dist/tui/builtin-commands.js +137 -0
- package/dist/tui/builtin-commands.js.map +1 -0
- package/dist/tui/editor-history.d.ts +6 -0
- package/dist/tui/editor-history.js +11 -0
- package/dist/tui/editor-history.js.map +1 -0
- package/dist/tui/editor-placeholder.d.ts +2 -0
- package/dist/tui/editor-placeholder.js +16 -0
- package/dist/tui/editor-placeholder.js.map +1 -0
- package/dist/tui/editor-with-placeholder.d.ts +8 -0
- package/dist/tui/editor-with-placeholder.js +49 -0
- package/dist/tui/editor-with-placeholder.js.map +1 -0
- package/dist/tui/hcent-autocomplete.d.ts +19 -0
- package/dist/tui/hcent-autocomplete.js +63 -0
- package/dist/tui/hcent-autocomplete.js.map +1 -0
- package/dist/tui/help-text.d.ts +1 -0
- package/dist/tui/help-text.js +15 -0
- package/dist/tui/help-text.js.map +1 -0
- package/dist/tui/index.d.ts +18 -0
- package/dist/tui/index.js +520 -0
- package/dist/tui/index.js.map +1 -0
- package/dist/tui/message-display.d.ts +8 -0
- package/dist/tui/message-display.js +41 -0
- package/dist/tui/message-display.js.map +1 -0
- package/dist/tui/pi-themes.d.ts +4 -0
- package/dist/tui/pi-themes.js +30 -0
- package/dist/tui/pi-themes.js.map +1 -0
- package/dist/tui/render-message.d.ts +3 -0
- package/dist/tui/render-message.js +32 -0
- package/dist/tui/render-message.js.map +1 -0
- package/dist/tui/thinking-loader.d.ts +17 -0
- package/dist/tui/thinking-loader.js +108 -0
- package/dist/tui/thinking-loader.js.map +1 -0
- package/dist/tui/user-message.d.ts +12 -0
- package/dist/tui/user-message.js +35 -0
- package/dist/tui/user-message.js.map +1 -0
- package/package.json +75 -0
package/dist/main.js
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { loadConfig } from './config/index.js';
|
|
4
|
+
import { createSession } from './session/index.js';
|
|
5
|
+
import { createProviderManager } from './provider/provider-manager.js';
|
|
6
|
+
import { createSessionStore } from './session/session-store.js';
|
|
7
|
+
import { createSkillRegistry } from './skill/index.js';
|
|
8
|
+
import { createCommandPalette } from './skill/command-palette.js';
|
|
9
|
+
import { createToolRegistry } from './tools/index.js';
|
|
10
|
+
import { hasApiKey } from './setup/index.js';
|
|
11
|
+
import { runPiTuiApp } from './tui/index.js';
|
|
12
|
+
export async function run() {
|
|
13
|
+
const cwd = process.cwd();
|
|
14
|
+
const config = loadConfig(cwd);
|
|
15
|
+
const needsSetup = !hasApiKey();
|
|
16
|
+
const session = createSession('你是一个终端编码助手(hcent)。你可以帮用户分析代码、查找文件、执行操作。');
|
|
17
|
+
const providerManager = createProviderManager(config);
|
|
18
|
+
const store = createSessionStore(undefined, [config.apiKey]);
|
|
19
|
+
const toolRegistry = createToolRegistry();
|
|
20
|
+
const skillRegistry = createSkillRegistry();
|
|
21
|
+
const home = homedir();
|
|
22
|
+
// 用户级 skill(低优先级)
|
|
23
|
+
await skillRegistry.loadFromDirectory(join(home, '.claude', 'skills'));
|
|
24
|
+
await skillRegistry.loadFromDirectory(join(home, '.cursor', 'skills'));
|
|
25
|
+
await skillRegistry.loadFromDirectory(join(home, '.agents', 'skills'));
|
|
26
|
+
await skillRegistry.loadFromDirectory(join(home, '.hcent', 'skills'));
|
|
27
|
+
// 项目级 skill(同名覆盖用户级)
|
|
28
|
+
await skillRegistry.loadFromDirectory(join(cwd, '.agents', 'skills'));
|
|
29
|
+
await skillRegistry.loadFromDirectory(join(cwd, '.hcent', 'skills'));
|
|
30
|
+
await skillRegistry.loadFromDirectory(join(cwd, '.cursor', 'skills'));
|
|
31
|
+
const palette = createCommandPalette(skillRegistry);
|
|
32
|
+
runPiTuiApp({
|
|
33
|
+
config,
|
|
34
|
+
session,
|
|
35
|
+
providerManager,
|
|
36
|
+
tools: toolRegistry,
|
|
37
|
+
store,
|
|
38
|
+
palette,
|
|
39
|
+
skillRegistry,
|
|
40
|
+
needsSetup,
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=main.js.map
|
package/dist/main.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"main.js","sourceRoot":"","sources":["../src/main.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAAE,qBAAqB,EAAE,MAAM,gCAAgC,CAAC;AACvE,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AACvD,OAAO,EAAE,oBAAoB,EAAE,MAAM,4BAA4B,CAAC;AAClE,OAAO,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AACtD,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC7C,OAAO,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAE7C,MAAM,CAAC,KAAK,UAAU,GAAG;IACvB,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,UAAU,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,UAAU,GAAG,CAAC,SAAS,EAAE,CAAC;IAEhC,MAAM,OAAO,GAAG,aAAa,CAC3B,yCAAyC,CAC1C,CAAC;IAEF,MAAM,eAAe,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IACtD,MAAM,KAAK,GAAG,kBAAkB,CAAC,SAAS,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC;IAC7D,MAAM,YAAY,GAAG,kBAAkB,EAAE,CAAC;IAE1C,MAAM,aAAa,GAAG,mBAAmB,EAAE,CAAC;IAC5C,MAAM,IAAI,GAAG,OAAO,EAAE,CAAC;IACvB,kBAAkB;IAClB,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACvE,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,qBAAqB;IACrB,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IACtE,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,CAAC;IACrE,MAAM,aAAa,CAAC,iBAAiB,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEtE,MAAM,OAAO,GAAG,oBAAoB,CAAC,aAAa,CAAC,CAAC;IAEpD,WAAW,CAAC;QACV,MAAM;QACN,OAAO;QACP,eAAe;QACf,KAAK,EAAE,YAAY;QACnB,KAAK;QACL,OAAO;QACP,aAAa;QACb,UAAU;KACX,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { AppConfig } from '../config/index.js';
|
|
2
|
+
import type { Message, ToolCall } from '../session/index.js';
|
|
3
|
+
import type { ToolSchema } from '../tools/index.js';
|
|
4
|
+
export interface ProviderRequest {
|
|
5
|
+
messages: Message[];
|
|
6
|
+
tools: ToolSchema[];
|
|
7
|
+
signal: AbortSignal;
|
|
8
|
+
}
|
|
9
|
+
export interface ProviderDelta {
|
|
10
|
+
contentDelta?: string;
|
|
11
|
+
toolCalls?: ToolCall[];
|
|
12
|
+
}
|
|
13
|
+
export interface Provider {
|
|
14
|
+
readonly model: string;
|
|
15
|
+
stream(req: ProviderRequest): AsyncIterable<ProviderDelta>;
|
|
16
|
+
}
|
|
17
|
+
export declare function createOpenAICompatibleProvider(config: AppConfig): Provider;
|
|
18
|
+
export interface MockResponse {
|
|
19
|
+
contentDelta?: string;
|
|
20
|
+
toolCalls?: ToolCall[];
|
|
21
|
+
delayMs?: number;
|
|
22
|
+
}
|
|
23
|
+
export declare function createMockProvider(model: string, responses: MockResponse[]): Provider;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import OpenAI from 'openai';
|
|
2
|
+
// ── 消息 & 工具格式转换 ──
|
|
3
|
+
function buildMessagesForAPI(messages) {
|
|
4
|
+
return messages.map((m) => {
|
|
5
|
+
const entry = { role: m.role, content: m.content };
|
|
6
|
+
if (m.toolCalls && m.toolCalls.length > 0) {
|
|
7
|
+
entry.tool_calls = m.toolCalls.map((tc) => ({
|
|
8
|
+
id: tc.id,
|
|
9
|
+
type: 'function',
|
|
10
|
+
function: { name: tc.name, arguments: JSON.stringify(tc.arguments) },
|
|
11
|
+
}));
|
|
12
|
+
}
|
|
13
|
+
if (m.toolCallId) {
|
|
14
|
+
entry.tool_call_id = m.toolCallId;
|
|
15
|
+
}
|
|
16
|
+
return entry;
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
function buildToolsForAPI(tools) {
|
|
20
|
+
if (tools.length === 0)
|
|
21
|
+
return undefined;
|
|
22
|
+
return tools.map((t) => ({
|
|
23
|
+
type: 'function',
|
|
24
|
+
function: {
|
|
25
|
+
name: t.name,
|
|
26
|
+
description: t.description,
|
|
27
|
+
parameters: t.parameters,
|
|
28
|
+
},
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
function buildToolCalls(accumulator) {
|
|
32
|
+
const calls = [];
|
|
33
|
+
for (const [, tc] of accumulator) {
|
|
34
|
+
if (!tc.id || !tc.name)
|
|
35
|
+
continue;
|
|
36
|
+
let parsedArgs = {};
|
|
37
|
+
try {
|
|
38
|
+
parsedArgs = JSON.parse(tc.args || '{}');
|
|
39
|
+
}
|
|
40
|
+
catch {
|
|
41
|
+
parsedArgs = {};
|
|
42
|
+
}
|
|
43
|
+
calls.push({ id: tc.id, name: tc.name, arguments: parsedArgs });
|
|
44
|
+
}
|
|
45
|
+
return calls;
|
|
46
|
+
}
|
|
47
|
+
// ── OpenAI 兼容 Provider(OpenAI SDK 驱动,DeepSeek 等)──
|
|
48
|
+
function accumulateStreamToolCalls(tcAccumulator, toolCalls) {
|
|
49
|
+
for (const tc of toolCalls) {
|
|
50
|
+
const acc = tcAccumulator.get(tc.index) ?? { args: '' };
|
|
51
|
+
if (tc.id)
|
|
52
|
+
acc.id = tc.id;
|
|
53
|
+
if (tc.function?.name)
|
|
54
|
+
acc.name = tc.function.name;
|
|
55
|
+
if (tc.function?.arguments)
|
|
56
|
+
acc.args += tc.function.arguments;
|
|
57
|
+
tcAccumulator.set(tc.index, acc);
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
async function* streamCompletionChunks(client, config, req) {
|
|
61
|
+
const stream = await client.chat.completions.create({
|
|
62
|
+
model: config.model,
|
|
63
|
+
messages: buildMessagesForAPI(req.messages),
|
|
64
|
+
tools: buildToolsForAPI(req.tools),
|
|
65
|
+
stream: true,
|
|
66
|
+
}, { signal: req.signal });
|
|
67
|
+
for await (const chunk of stream) {
|
|
68
|
+
yield chunk;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
export function createOpenAICompatibleProvider(config) {
|
|
72
|
+
const client = new OpenAI({
|
|
73
|
+
baseURL: config.baseUrl,
|
|
74
|
+
apiKey: config.apiKey || 'sk-placeholder',
|
|
75
|
+
timeout: config.timeoutMs,
|
|
76
|
+
maxRetries: config.maxRetries,
|
|
77
|
+
});
|
|
78
|
+
return {
|
|
79
|
+
model: config.model,
|
|
80
|
+
async *stream(req) {
|
|
81
|
+
const tcAccumulator = new Map();
|
|
82
|
+
for await (const chunk of streamCompletionChunks(client, config, req)) {
|
|
83
|
+
const delta = chunk.choices[0]?.delta;
|
|
84
|
+
if (!delta)
|
|
85
|
+
continue;
|
|
86
|
+
if (delta.content) {
|
|
87
|
+
yield { contentDelta: delta.content };
|
|
88
|
+
}
|
|
89
|
+
if (delta.tool_calls) {
|
|
90
|
+
accumulateStreamToolCalls(tcAccumulator, delta.tool_calls);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
const toolCalls = buildToolCalls(tcAccumulator);
|
|
94
|
+
if (toolCalls.length > 0) {
|
|
95
|
+
yield { toolCalls };
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
export function createMockProvider(model, responses) {
|
|
101
|
+
let callIndex = -1;
|
|
102
|
+
return {
|
|
103
|
+
model,
|
|
104
|
+
async *stream(_req) {
|
|
105
|
+
callIndex++;
|
|
106
|
+
const r = responses[callIndex];
|
|
107
|
+
if (!r)
|
|
108
|
+
return;
|
|
109
|
+
if (r.delayMs) {
|
|
110
|
+
await new Promise((resolve) => setTimeout(resolve, r.delayMs));
|
|
111
|
+
}
|
|
112
|
+
if (r.contentDelta) {
|
|
113
|
+
// 模拟流式逐字输出
|
|
114
|
+
for (let i = 0; i < r.contentDelta.length; i++) {
|
|
115
|
+
yield { contentDelta: r.contentDelta[i] };
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (r.toolCalls) {
|
|
119
|
+
yield { toolCalls: r.toolCalls };
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/provider/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AppConfig, ModelConfig } from '../config/index.js';
|
|
2
|
+
import { type Provider } from './index.js';
|
|
3
|
+
export interface ProviderManager {
|
|
4
|
+
readonly current: Provider;
|
|
5
|
+
readonly activeModelConfig: ModelConfig;
|
|
6
|
+
switch(name: string): void;
|
|
7
|
+
listModels(): ModelConfig[];
|
|
8
|
+
}
|
|
9
|
+
export declare function createProviderManager(config: AppConfig): ProviderManager;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { createOpenAICompatibleProvider } from './index.js';
|
|
2
|
+
export function createProviderManager(config) {
|
|
3
|
+
let activeConfig = findModel(config, config.activeModel);
|
|
4
|
+
let provider = createProvider(activeConfig);
|
|
5
|
+
function findModel(cfg, name) {
|
|
6
|
+
const found = cfg.models.find((m) => m.name === name);
|
|
7
|
+
if (!found)
|
|
8
|
+
throw new Error(`模型 ${name} 不存在`);
|
|
9
|
+
return found;
|
|
10
|
+
}
|
|
11
|
+
function createProvider(mc) {
|
|
12
|
+
const providerConfig = {
|
|
13
|
+
...config,
|
|
14
|
+
model: mc.model,
|
|
15
|
+
baseUrl: mc.baseUrl,
|
|
16
|
+
apiKey: mc.apiKey,
|
|
17
|
+
timeoutMs: mc.timeoutMs ?? config.timeoutMs,
|
|
18
|
+
maxRetries: mc.maxRetries ?? config.maxRetries,
|
|
19
|
+
};
|
|
20
|
+
switch (config.provider) {
|
|
21
|
+
case 'openai-compatible':
|
|
22
|
+
case 'deepseek':
|
|
23
|
+
default:
|
|
24
|
+
return createOpenAICompatibleProvider(providerConfig);
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
return {
|
|
28
|
+
get current() {
|
|
29
|
+
return provider;
|
|
30
|
+
},
|
|
31
|
+
get activeModelConfig() {
|
|
32
|
+
return activeConfig;
|
|
33
|
+
},
|
|
34
|
+
switch(name) {
|
|
35
|
+
activeConfig = findModel(config, name);
|
|
36
|
+
provider = createProvider(activeConfig);
|
|
37
|
+
},
|
|
38
|
+
listModels() {
|
|
39
|
+
return config.models.map((m) => ({ ...m, apiKey: m.apiKey ? '***' : '' }));
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=provider-manager.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"provider-manager.js","sourceRoot":"","sources":["../../src/provider/provider-manager.ts"],"names":[],"mappings":"AACA,OAAO,EAAiB,8BAA8B,EAAE,MAAM,YAAY,CAAC;AAS3E,MAAM,UAAU,qBAAqB,CAAC,MAAiB;IACrD,IAAI,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,WAAW,CAAC,CAAC;IACzD,IAAI,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;IAE5C,SAAS,SAAS,CAAC,GAAc,EAAE,IAAY;QAC7C,MAAM,KAAK,GAAG,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACtD,IAAI,CAAC,KAAK;YAAE,MAAM,IAAI,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,CAAC;QAC9C,OAAO,KAAK,CAAC;IACf,CAAC;IAED,SAAS,cAAc,CAAC,EAAe;QACrC,MAAM,cAAc,GAAc;YAChC,GAAG,MAAM;YACT,KAAK,EAAE,EAAE,CAAC,KAAK;YACf,OAAO,EAAE,EAAE,CAAC,OAAO;YACnB,MAAM,EAAE,EAAE,CAAC,MAAM;YACjB,SAAS,EAAE,EAAE,CAAC,SAAS,IAAI,MAAM,CAAC,SAAS;YAC3C,UAAU,EAAE,EAAE,CAAC,UAAU,IAAI,MAAM,CAAC,UAAU;SAC/C,CAAC;QACF,QAAQ,MAAM,CAAC,QAAQ,EAAE,CAAC;YACxB,KAAK,mBAAmB,CAAC;YACzB,KAAK,UAAU,CAAC;YAChB;gBACE,OAAO,8BAA8B,CAAC,cAAc,CAAC,CAAC;QAC1D,CAAC;IACH,CAAC;IAED,OAAO;QACL,IAAI,OAAO;YACT,OAAO,QAAQ,CAAC;QAClB,CAAC;QACD,IAAI,iBAAiB;YACnB,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,MAAM,CAAC,IAAY;YACjB,YAAY,GAAG,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;YACvC,QAAQ,GAAG,cAAc,CAAC,YAAY,CAAC,CAAC;QAC1C,CAAC;QACD,UAAU;YACR,OAAO,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC;QAC7E,CAAC;KACF,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
export type Role = 'system' | 'user' | 'assistant' | 'tool';
|
|
2
|
+
export interface ToolCall {
|
|
3
|
+
id: string;
|
|
4
|
+
name: string;
|
|
5
|
+
arguments: Record<string, unknown>;
|
|
6
|
+
}
|
|
7
|
+
export type MessageKind = 'normal' | 'permission_reject' | 'error' | 'summary' | 'skill' | 'base';
|
|
8
|
+
export interface Message {
|
|
9
|
+
role: Role;
|
|
10
|
+
content: string;
|
|
11
|
+
toolCalls?: ToolCall[];
|
|
12
|
+
toolCallId?: string;
|
|
13
|
+
kind?: MessageKind;
|
|
14
|
+
ts: string;
|
|
15
|
+
}
|
|
16
|
+
export declare function createMessage(params: {
|
|
17
|
+
role: Role;
|
|
18
|
+
content: string;
|
|
19
|
+
toolCalls?: ToolCall[];
|
|
20
|
+
toolCallId?: string;
|
|
21
|
+
kind?: MessageKind;
|
|
22
|
+
}): Message;
|
|
23
|
+
export interface SkillMeta {
|
|
24
|
+
name: string;
|
|
25
|
+
filePath: string;
|
|
26
|
+
description: string;
|
|
27
|
+
}
|
|
28
|
+
export interface Session {
|
|
29
|
+
readonly id: string;
|
|
30
|
+
messages: Message[];
|
|
31
|
+
readonly activeSkills: SkillMeta[];
|
|
32
|
+
append(m: Message): void;
|
|
33
|
+
clear(): void;
|
|
34
|
+
snapshot(): Message[];
|
|
35
|
+
addSkill(name: string, filePath: string, description: string, pointerContent: string): void;
|
|
36
|
+
removeSkill(name: string): void;
|
|
37
|
+
clearSkills(): void;
|
|
38
|
+
}
|
|
39
|
+
export declare function createSession(systemPrompt?: string): Session;
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { randomUUID } from 'node:crypto';
|
|
2
|
+
// ── 工厂函数 ──
|
|
3
|
+
function now() {
|
|
4
|
+
return new Date().toISOString();
|
|
5
|
+
}
|
|
6
|
+
export function createMessage(params) {
|
|
7
|
+
return {
|
|
8
|
+
role: params.role,
|
|
9
|
+
content: params.content,
|
|
10
|
+
toolCalls: params.toolCalls,
|
|
11
|
+
toolCallId: params.toolCallId,
|
|
12
|
+
kind: params.kind,
|
|
13
|
+
ts: now(),
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
export function createSession(systemPrompt) {
|
|
17
|
+
const id = randomUUID();
|
|
18
|
+
const messages = [];
|
|
19
|
+
const activeSkills = [];
|
|
20
|
+
if (systemPrompt) {
|
|
21
|
+
messages.push(createMessage({ role: 'system', content: systemPrompt, kind: 'base' }));
|
|
22
|
+
}
|
|
23
|
+
return {
|
|
24
|
+
id,
|
|
25
|
+
messages,
|
|
26
|
+
get activeSkills() {
|
|
27
|
+
return activeSkills;
|
|
28
|
+
},
|
|
29
|
+
append(m) {
|
|
30
|
+
messages.push(m);
|
|
31
|
+
},
|
|
32
|
+
clear() {
|
|
33
|
+
const systemMessages = messages.filter((m) => m.role === 'system');
|
|
34
|
+
messages.length = 0;
|
|
35
|
+
messages.push(...systemMessages);
|
|
36
|
+
},
|
|
37
|
+
snapshot() {
|
|
38
|
+
return structuredClone(messages);
|
|
39
|
+
},
|
|
40
|
+
addSkill(name, filePath, description, pointerContent) {
|
|
41
|
+
if (activeSkills.some((s) => s.name === name))
|
|
42
|
+
return;
|
|
43
|
+
activeSkills.push({ name, filePath, description });
|
|
44
|
+
messages.push(createMessage({ role: 'system', content: pointerContent, kind: 'skill' }));
|
|
45
|
+
},
|
|
46
|
+
removeSkill(name) {
|
|
47
|
+
const idx = activeSkills.findIndex((s) => s.name === name);
|
|
48
|
+
if (idx === -1)
|
|
49
|
+
return;
|
|
50
|
+
activeSkills.splice(idx, 1);
|
|
51
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
52
|
+
const m = messages[i];
|
|
53
|
+
if (m.role === 'system' && m.kind === 'skill' && m.content.includes(`**${name}**`)) {
|
|
54
|
+
messages.splice(i, 1);
|
|
55
|
+
break;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
clearSkills() {
|
|
60
|
+
activeSkills.length = 0;
|
|
61
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
62
|
+
if (messages[i].role === 'system' && messages[i].kind === 'skill') {
|
|
63
|
+
messages.splice(i, 1);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/session/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { type Session, type Message } from './index.js';
|
|
2
|
+
export interface SessionMeta {
|
|
3
|
+
id: string;
|
|
4
|
+
title: string;
|
|
5
|
+
createdAt: string;
|
|
6
|
+
updatedAt: string;
|
|
7
|
+
messageCount: number;
|
|
8
|
+
lastModel: string;
|
|
9
|
+
}
|
|
10
|
+
export interface SessionStore {
|
|
11
|
+
save(session: Session, model: string): Promise<void>;
|
|
12
|
+
load(id: string): Promise<{
|
|
13
|
+
messages: Message[];
|
|
14
|
+
meta: SessionMeta;
|
|
15
|
+
} | null>;
|
|
16
|
+
list(): Promise<SessionMeta[]>;
|
|
17
|
+
delete(id: string): Promise<boolean>;
|
|
18
|
+
}
|
|
19
|
+
export declare function createSessionStore(dir?: string, apiKeys?: string[]): SessionStore;
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, readdirSync, mkdirSync, unlinkSync } from 'node:fs';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
function defaultDir() {
|
|
5
|
+
return join(homedir(), '.config', 'hcent', 'sessions');
|
|
6
|
+
}
|
|
7
|
+
function extractTitle(messages) {
|
|
8
|
+
const firstUser = messages.find((m) => m.role === 'user');
|
|
9
|
+
if (!firstUser)
|
|
10
|
+
return '(无标题)';
|
|
11
|
+
const text = firstUser.content.slice(0, 50);
|
|
12
|
+
return text.length < firstUser.content.length ? text + '…' : text;
|
|
13
|
+
}
|
|
14
|
+
function redactApiKey(messages, apiKeys) {
|
|
15
|
+
if (apiKeys.length === 0)
|
|
16
|
+
return messages;
|
|
17
|
+
return messages.map((m) => {
|
|
18
|
+
let content = m.content;
|
|
19
|
+
for (const key of apiKeys) {
|
|
20
|
+
if (key)
|
|
21
|
+
content = content.replaceAll(key, '***');
|
|
22
|
+
}
|
|
23
|
+
return content === m.content ? m : { ...m, content };
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
export function createSessionStore(dir, apiKeys) {
|
|
27
|
+
const storeDir = dir ?? defaultDir();
|
|
28
|
+
function ensureDir() {
|
|
29
|
+
try {
|
|
30
|
+
mkdirSync(storeDir, { recursive: true });
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
// already exists
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function filePath(id) {
|
|
37
|
+
return join(storeDir, `${id}.json`);
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
async save(session, model) {
|
|
41
|
+
try {
|
|
42
|
+
ensureDir();
|
|
43
|
+
const now = new Date().toISOString();
|
|
44
|
+
const existing = readMeta(filePath(session.id));
|
|
45
|
+
const meta = {
|
|
46
|
+
id: session.id,
|
|
47
|
+
title: extractTitle(session.messages),
|
|
48
|
+
createdAt: existing?.createdAt ?? now,
|
|
49
|
+
updatedAt: now,
|
|
50
|
+
messageCount: session.messages.length,
|
|
51
|
+
lastModel: model,
|
|
52
|
+
};
|
|
53
|
+
const safeMessages = redactApiKey(session.messages, apiKeys ?? []);
|
|
54
|
+
writeFileSync(filePath(session.id), JSON.stringify({ meta, messages: safeMessages }, null, 2), 'utf-8');
|
|
55
|
+
}
|
|
56
|
+
catch (err) {
|
|
57
|
+
console.warn('保存会话失败:', err instanceof Error ? err.message : String(err));
|
|
58
|
+
}
|
|
59
|
+
},
|
|
60
|
+
async load(id) {
|
|
61
|
+
try {
|
|
62
|
+
const raw = readFileSync(filePath(id), 'utf-8');
|
|
63
|
+
const data = JSON.parse(raw);
|
|
64
|
+
if (!data.meta || !data.messages)
|
|
65
|
+
return null;
|
|
66
|
+
return { messages: data.messages, meta: data.meta };
|
|
67
|
+
}
|
|
68
|
+
catch {
|
|
69
|
+
return null;
|
|
70
|
+
}
|
|
71
|
+
},
|
|
72
|
+
async list() {
|
|
73
|
+
try {
|
|
74
|
+
ensureDir();
|
|
75
|
+
const files = readdirSync(storeDir).filter((f) => f.endsWith('.json'));
|
|
76
|
+
const metas = [];
|
|
77
|
+
for (const file of files) {
|
|
78
|
+
const meta = readMeta(join(storeDir, file));
|
|
79
|
+
if (meta)
|
|
80
|
+
metas.push(meta);
|
|
81
|
+
}
|
|
82
|
+
return metas.sort((a, b) => b.updatedAt.localeCompare(a.updatedAt));
|
|
83
|
+
}
|
|
84
|
+
catch {
|
|
85
|
+
return [];
|
|
86
|
+
}
|
|
87
|
+
},
|
|
88
|
+
async delete(id) {
|
|
89
|
+
try {
|
|
90
|
+
unlinkSync(filePath(id));
|
|
91
|
+
return true;
|
|
92
|
+
}
|
|
93
|
+
catch {
|
|
94
|
+
return false;
|
|
95
|
+
}
|
|
96
|
+
},
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
function readMeta(path) {
|
|
100
|
+
try {
|
|
101
|
+
const raw = readFileSync(path, 'utf-8');
|
|
102
|
+
const data = JSON.parse(raw);
|
|
103
|
+
return data.meta ?? null;
|
|
104
|
+
}
|
|
105
|
+
catch {
|
|
106
|
+
return null;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
//# sourceMappingURL=session-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-store.js","sourceRoot":"","sources":["../../src/session/session-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,WAAW,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAC1F,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAmBlC,SAAS,UAAU;IACjB,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;AACzD,CAAC;AAED,SAAS,YAAY,CAAC,QAAmB;IACvC,MAAM,SAAS,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,SAAS;QAAE,OAAO,OAAO,CAAC;IAC/B,MAAM,IAAI,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC5C,OAAO,IAAI,CAAC,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;AACpE,CAAC;AAED,SAAS,YAAY,CAAC,QAAmB,EAAE,OAAiB;IAC1D,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO,QAAQ,CAAC;IAC1C,OAAO,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;QACxB,IAAI,OAAO,GAAG,CAAC,CAAC,OAAO,CAAC;QACxB,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;YAC1B,IAAI,GAAG;gBAAE,OAAO,GAAG,OAAO,CAAC,UAAU,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,OAAO,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,OAAO,EAAE,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,GAAY,EAAE,OAAkB;IACjE,MAAM,QAAQ,GAAG,GAAG,IAAI,UAAU,EAAE,CAAC;IAErC,SAAS,SAAS;QAChB,IAAI,CAAC;YACH,SAAS,CAAC,QAAQ,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAC3C,CAAC;QAAC,MAAM,CAAC;YACP,iBAAiB;QACnB,CAAC;IACH,CAAC;IAED,SAAS,QAAQ,CAAC,EAAU;QAC1B,OAAO,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,OAAO;QACL,KAAK,CAAC,IAAI,CAAC,OAAgB,EAAE,KAAa;YACxC,IAAI,CAAC;gBACH,SAAS,EAAE,CAAC;gBACZ,MAAM,GAAG,GAAG,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;gBACrC,MAAM,QAAQ,GAAG,QAAQ,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;gBAChD,MAAM,IAAI,GAAgB;oBACxB,EAAE,EAAE,OAAO,CAAC,EAAE;oBACd,KAAK,EAAE,YAAY,CAAC,OAAO,CAAC,QAAQ,CAAC;oBACrC,SAAS,EAAE,QAAQ,EAAE,SAAS,IAAI,GAAG;oBACrC,SAAS,EAAE,GAAG;oBACd,YAAY,EAAE,OAAO,CAAC,QAAQ,CAAC,MAAM;oBACrC,SAAS,EAAE,KAAK;iBACjB,CAAC;gBACF,MAAM,YAAY,GAAG,YAAY,CAAC,OAAO,CAAC,QAAQ,EAAE,OAAO,IAAI,EAAE,CAAC,CAAC;gBACnE,aAAa,CAAC,QAAQ,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC;YAC1G,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC5E,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,EAAU;YACnB,IAAI,CAAC;gBACH,MAAM,GAAG,GAAG,YAAY,CAAC,QAAQ,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;gBAChD,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gBAC7B,IAAI,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC,IAAI,CAAC,QAAQ;oBAAE,OAAO,IAAI,CAAC;gBAC9C,OAAO,EAAE,QAAQ,EAAE,IAAI,CAAC,QAAqB,EAAE,IAAI,EAAE,IAAI,CAAC,IAAmB,EAAE,CAAC;YAClF,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC;QAED,KAAK,CAAC,IAAI;YACR,IAAI,CAAC;gBACH,SAAS,EAAE,CAAC;gBACZ,MAAM,KAAK,GAAG,WAAW,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,CAAC;gBACvE,MAAM,KAAK,GAAkB,EAAE,CAAC;gBAChC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;oBACzB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC,CAAC;oBAC5C,IAAI,IAAI;wBAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;gBAC7B,CAAC;gBACD,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;YACtE,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,EAAE,CAAC;YACZ,CAAC;QACH,CAAC;QAED,KAAK,CAAC,MAAM,CAAC,EAAU;YACrB,IAAI,CAAC;gBACH,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC;gBACzB,OAAO,IAAI,CAAC;YACd,CAAC;YAAC,MAAM,CAAC;gBACP,OAAO,KAAK,CAAC;YACf,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QACxC,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC7B,OAAO,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC;IAC3B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export declare const DEFAULT_BASE_URL = "https://api.deepseek.com";
|
|
2
|
+
export declare const DEFAULT_MODEL = "deepseek-v4-pro";
|
|
3
|
+
/** 检查是否有任何形式可用的 apiKey(环境变量 / 用户全局配置 / 项目级配置) */
|
|
4
|
+
export declare function hasApiKey(): boolean;
|
|
5
|
+
/** 返回用户全局配置路径 */
|
|
6
|
+
export declare function userConfigPath(): string;
|
|
7
|
+
/** 引导提示文本(供 TUI 在输入栏上方渲染) */
|
|
8
|
+
export declare function setupGuideLines(): string[];
|
|
9
|
+
/** 将 API Key 写入用户全局配置文件 */
|
|
10
|
+
export declare function writeUserConfig(apiKey: string, baseUrl?: string): void;
|
|
11
|
+
export declare function runSetup(): Promise<void>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
// 配置引导工具。供 bin 入口和 main/TUI 使用。
|
|
2
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { homedir } from 'node:os';
|
|
5
|
+
import { createInterface } from 'node:readline';
|
|
6
|
+
export const DEFAULT_BASE_URL = 'https://api.deepseek.com';
|
|
7
|
+
export const DEFAULT_MODEL = 'deepseek-v4-pro';
|
|
8
|
+
/** 检查配置文件是否含有 apiKey */
|
|
9
|
+
function configFileHasApiKey(path) {
|
|
10
|
+
try {
|
|
11
|
+
const cfg = JSON.parse(readFileSync(path, 'utf-8'));
|
|
12
|
+
return Boolean(cfg.apiKey) || (cfg.models?.length > 0 && cfg.models[0].apiKey);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
/** 检查是否有任何形式可用的 apiKey(环境变量 / 用户全局配置 / 项目级配置) */
|
|
19
|
+
export function hasApiKey() {
|
|
20
|
+
if (process.env.HCENT_API_KEY)
|
|
21
|
+
return true;
|
|
22
|
+
if (configFileHasApiKey(join(homedir(), '.hcent', 'config.json')))
|
|
23
|
+
return true;
|
|
24
|
+
return configFileHasApiKey(join(process.cwd(), '.hcent', 'config.json'));
|
|
25
|
+
}
|
|
26
|
+
/** 返回用户全局配置路径 */
|
|
27
|
+
export function userConfigPath() {
|
|
28
|
+
return join(homedir(), '.hcent', 'config.json');
|
|
29
|
+
}
|
|
30
|
+
/** 引导提示文本(供 TUI 在输入栏上方渲染) */
|
|
31
|
+
export function setupGuideLines() {
|
|
32
|
+
return [
|
|
33
|
+
'欢迎使用 hcent!首次运行需要配置 API Key。',
|
|
34
|
+
'',
|
|
35
|
+
'请在下方输入 DeepSeek API Key 开始使用:',
|
|
36
|
+
'',
|
|
37
|
+
`(配置将保存到 ${userConfigPath()},之后无需重复输入)`,
|
|
38
|
+
'',
|
|
39
|
+
'也可以退出后通过以下方式配置:',
|
|
40
|
+
` 环境变量: HCENT_API_KEY=your-key`,
|
|
41
|
+
` 项目配置: .hcent/config.json`,
|
|
42
|
+
` 命令行向导: hcent --setup`,
|
|
43
|
+
];
|
|
44
|
+
}
|
|
45
|
+
/** 将 API Key 写入用户全局配置文件 */
|
|
46
|
+
export function writeUserConfig(apiKey, baseUrl) {
|
|
47
|
+
const dir = join(homedir(), '.hcent');
|
|
48
|
+
if (!existsSync(dir))
|
|
49
|
+
mkdirSync(dir, { recursive: true });
|
|
50
|
+
const resolvedBaseUrl = baseUrl?.trim() || DEFAULT_BASE_URL;
|
|
51
|
+
const config = {
|
|
52
|
+
apiKey: apiKey.trim(),
|
|
53
|
+
model: DEFAULT_MODEL,
|
|
54
|
+
baseUrl: resolvedBaseUrl,
|
|
55
|
+
provider: 'deepseek',
|
|
56
|
+
maxLoops: 68,
|
|
57
|
+
timeoutMs: 60_000,
|
|
58
|
+
maxRetries: 2,
|
|
59
|
+
models: [
|
|
60
|
+
{
|
|
61
|
+
name: DEFAULT_MODEL,
|
|
62
|
+
model: DEFAULT_MODEL,
|
|
63
|
+
baseUrl: resolvedBaseUrl,
|
|
64
|
+
apiKey: apiKey.trim(),
|
|
65
|
+
maxContextTokens: 65536,
|
|
66
|
+
},
|
|
67
|
+
],
|
|
68
|
+
activeModel: DEFAULT_MODEL,
|
|
69
|
+
searchApiKey: '',
|
|
70
|
+
};
|
|
71
|
+
writeFileSync(join(dir, 'config.json'), JSON.stringify(config, null, 2), 'utf-8');
|
|
72
|
+
process.env.HCENT_API_KEY = apiKey.trim();
|
|
73
|
+
}
|
|
74
|
+
// ── 保留 --setup 的 readline 交互式配置(TUI 之外也能用) ──
|
|
75
|
+
function question(rl, prompt) {
|
|
76
|
+
return new Promise((resolve) => rl.question(prompt, resolve));
|
|
77
|
+
}
|
|
78
|
+
export async function runSetup() {
|
|
79
|
+
const rl = createInterface({ input: process.stdin, output: process.stdout });
|
|
80
|
+
console.log('');
|
|
81
|
+
console.log('╔══════════════════════════════════════╗');
|
|
82
|
+
console.log('║ hcent 首次配置向导 ║');
|
|
83
|
+
console.log('╚══════════════════════════════════════╝');
|
|
84
|
+
console.log('');
|
|
85
|
+
console.log('将创建用户全局配置文件,所有项目共享。');
|
|
86
|
+
console.log('');
|
|
87
|
+
const apiKey = await question(rl, 'API Key: ');
|
|
88
|
+
const model = await question(rl, `模型标识 (默认 ${DEFAULT_MODEL}): `);
|
|
89
|
+
const baseUrl = await question(rl, `API Base URL (默认 ${DEFAULT_BASE_URL}): `);
|
|
90
|
+
rl.close();
|
|
91
|
+
writeUserConfig(apiKey, baseUrl);
|
|
92
|
+
console.log('');
|
|
93
|
+
console.log(`配置已写入: ${userConfigPath()}`);
|
|
94
|
+
console.log('现在可以运行 hcent 开始使用。');
|
|
95
|
+
console.log('');
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/setup/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { SkillRegistry } from './index.js';
|
|
2
|
+
export interface PaletteEntry {
|
|
3
|
+
type: 'command' | 'skill';
|
|
4
|
+
name: string;
|
|
5
|
+
description: string;
|
|
6
|
+
keywords: string[];
|
|
7
|
+
}
|
|
8
|
+
export interface CommandPalette {
|
|
9
|
+
entries(): PaletteEntry[];
|
|
10
|
+
search(query: string): PaletteEntry[];
|
|
11
|
+
}
|
|
12
|
+
export declare function createCommandPalette(skills: SkillRegistry): CommandPalette;
|