chatccc 0.2.245 → 0.2.246
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 +8 -8
- package/deepccc-agent/README.md +28 -14
- package/deepccc-agent/os-prompts/darwin.md +8 -8
- package/deepccc-agent/os-prompts/linux.md +8 -8
- package/deepccc-agent/os-prompts/win32.md +9 -9
- package/deepccc-agent/package-lock.json +70 -2
- package/deepccc-agent/package.json +65 -63
- package/deepccc-agent/src/__tests__/chat-session.test.ts +741 -682
- package/deepccc-agent/src/__tests__/config.test.ts +34 -26
- package/deepccc-agent/src/__tests__/permissions.test.ts +199 -195
- package/deepccc-agent/src/__tests__/privacy.test.ts +12 -8
- package/deepccc-agent/src/cli.ts +20 -9
- package/deepccc-agent/src/config.ts +101 -88
- package/deepccc-agent/src/index.ts +86 -61
- package/package.json +74 -73
- package/src/__tests__/builtin-chat-session.test.ts +532 -522
- package/src/__tests__/builtin-permissions.test.ts +219 -211
- package/src/__tests__/ccc-adapter.test.ts +194 -185
- package/src/__tests__/session.test.ts +369 -369
- package/src/adapters/adapter-interface.ts +42 -42
- package/src/adapters/ccc-adapter.ts +150 -149
- package/src/session.ts +323 -323
|
@@ -1,88 +1,101 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
|
-
import { dirname, join } from "node:path";
|
|
4
|
-
|
|
5
|
-
export
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
const
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const
|
|
47
|
-
return
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
function
|
|
51
|
-
const value = env
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
return
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
function
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
return
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
|
|
5
|
+
export type DeepCccProvider = "openai" | "anthropic";
|
|
6
|
+
|
|
7
|
+
export interface DeepCccConfig {
|
|
8
|
+
/** API protocol/provider. Defaults to OpenAI-compatible. */
|
|
9
|
+
provider: DeepCccProvider;
|
|
10
|
+
apiKey: string;
|
|
11
|
+
baseURL: string;
|
|
12
|
+
model: string;
|
|
13
|
+
/** Reasoning effort(none/minimal/low/medium/high/xhigh/max),留空不传 reasoning_effort */
|
|
14
|
+
effort: string;
|
|
15
|
+
/** 主对话是否使用流式请求;默认开启 */
|
|
16
|
+
streaming: boolean;
|
|
17
|
+
rawStreamLogs: {
|
|
18
|
+
enabled: boolean;
|
|
19
|
+
maxBytesPerTurn: number;
|
|
20
|
+
retentionDays: number;
|
|
21
|
+
keepCompleted: boolean;
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export const DEEPCCC_HOME = join(homedir(), ".deepccc");
|
|
26
|
+
export const RAW_STREAM_LOGS_DIR = join(DEEPCCC_HOME, "raw-stream-logs");
|
|
27
|
+
const CONFIG_PATH = join(DEEPCCC_HOME, "config.json");
|
|
28
|
+
|
|
29
|
+
const DEFAULT_CONFIG: DeepCccConfig = {
|
|
30
|
+
provider: "openai",
|
|
31
|
+
apiKey: "",
|
|
32
|
+
baseURL: "https://api.deepseek.com/v1",
|
|
33
|
+
model: "deepseek-v4-pro",
|
|
34
|
+
effort: "",
|
|
35
|
+
streaming: true,
|
|
36
|
+
rawStreamLogs: {
|
|
37
|
+
enabled: false,
|
|
38
|
+
maxBytesPerTurn: 1024 * 1024,
|
|
39
|
+
retentionDays: 7,
|
|
40
|
+
keepCompleted: false,
|
|
41
|
+
},
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
function readConfigFile(): Partial<DeepCccConfig> {
|
|
45
|
+
if (!existsSync(CONFIG_PATH)) return {};
|
|
46
|
+
const raw = JSON.parse(readFileSync(CONFIG_PATH, "utf8")) as Partial<DeepCccConfig>;
|
|
47
|
+
return raw && typeof raw === "object" ? raw : {};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
function env(name: string): string | undefined {
|
|
51
|
+
const value = process.env[name]?.trim();
|
|
52
|
+
return value ? value : undefined;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
function boolEnv(name: string): boolean | undefined {
|
|
56
|
+
const value = env(name)?.toLowerCase();
|
|
57
|
+
if (value === undefined) return undefined;
|
|
58
|
+
if (["1", "true", "yes", "on"].includes(value)) return true;
|
|
59
|
+
if (["0", "false", "no", "off"].includes(value)) return false;
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
function numberEnv(name: string): number | undefined {
|
|
64
|
+
const value = Number(env(name));
|
|
65
|
+
return Number.isFinite(value) && value >= 0 ? value : undefined;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function normalizeDeepCccProvider(value: unknown): DeepCccProvider {
|
|
69
|
+
if (value === undefined || value === null || String(value).trim() === "") return "openai";
|
|
70
|
+
const normalized = String(value).trim().toLowerCase();
|
|
71
|
+
if (normalized === "openai" || normalized === "anthropic") return normalized;
|
|
72
|
+
throw new Error(`DEEPCCC_PROVIDER/provider must be "openai" or "anthropic", received: ${String(value)}`);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
function loadConfig(): DeepCccConfig {
|
|
76
|
+
const file = readConfigFile();
|
|
77
|
+
const rawLogs: Partial<DeepCccConfig["rawStreamLogs"]> = file.rawStreamLogs && typeof file.rawStreamLogs === "object"
|
|
78
|
+
? file.rawStreamLogs
|
|
79
|
+
: {};
|
|
80
|
+
|
|
81
|
+
return {
|
|
82
|
+
provider: normalizeDeepCccProvider(env("DEEPCCC_PROVIDER") ?? file.provider ?? DEFAULT_CONFIG.provider),
|
|
83
|
+
apiKey: env("DEEPCCC_API_KEY") ?? env("DEEPSEEK_API_KEY") ?? file.apiKey ?? DEFAULT_CONFIG.apiKey,
|
|
84
|
+
baseURL: env("DEEPCCC_BASE_URL") ?? env("DEEPSEEK_BASE_URL") ?? file.baseURL ?? DEFAULT_CONFIG.baseURL,
|
|
85
|
+
model: env("DEEPCCC_MODEL") ?? env("DEEPSEEK_MODEL") ?? file.model ?? DEFAULT_CONFIG.model,
|
|
86
|
+
effort: env("DEEPCCC_EFFORT") ?? env("DEEPSEEK_EFFORT") ?? file.effort ?? DEFAULT_CONFIG.effort,
|
|
87
|
+
streaming: boolEnv("DEEPCCC_STREAMING") ?? file.streaming ?? DEFAULT_CONFIG.streaming,
|
|
88
|
+
rawStreamLogs: {
|
|
89
|
+
enabled: boolEnv("DEEPCCC_RAW_STREAM_LOGS") ?? rawLogs.enabled ?? DEFAULT_CONFIG.rawStreamLogs.enabled,
|
|
90
|
+
maxBytesPerTurn: numberEnv("DEEPCCC_RAW_STREAM_MAX_BYTES") ?? rawLogs.maxBytesPerTurn ?? DEFAULT_CONFIG.rawStreamLogs.maxBytesPerTurn,
|
|
91
|
+
retentionDays: numberEnv("DEEPCCC_RAW_STREAM_RETENTION_DAYS") ?? rawLogs.retentionDays ?? DEFAULT_CONFIG.rawStreamLogs.retentionDays,
|
|
92
|
+
keepCompleted: boolEnv("DEEPCCC_RAW_STREAM_KEEP_COMPLETED") ?? rawLogs.keepCompleted ?? DEFAULT_CONFIG.rawStreamLogs.keepCompleted,
|
|
93
|
+
},
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
export function ensureConfigDir(): void {
|
|
98
|
+
mkdirSync(dirname(CONFIG_PATH), { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const config = loadConfig();
|
|
@@ -5,13 +5,19 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import { createOpenAICompatible } from "@ai-sdk/openai-compatible";
|
|
8
|
+
import { createAnthropic } from "@ai-sdk/anthropic";
|
|
8
9
|
import { generateText, isLoopFinished, stepCountIs, streamText, type TextStreamPart } from "ai";
|
|
9
10
|
import { existsSync, readFileSync } from "node:fs";
|
|
10
11
|
import { homedir } from "node:os";
|
|
11
12
|
import { join } from "node:path";
|
|
12
13
|
import { fileURLToPath } from "node:url";
|
|
13
14
|
|
|
14
|
-
import {
|
|
15
|
+
import {
|
|
16
|
+
config as appConfig,
|
|
17
|
+
normalizeDeepCccProvider,
|
|
18
|
+
RAW_STREAM_LOGS_DIR,
|
|
19
|
+
type DeepCccProvider,
|
|
20
|
+
} from "./config.js";
|
|
15
21
|
import {
|
|
16
22
|
createRawStreamLog,
|
|
17
23
|
type RawStreamLogHandle,
|
|
@@ -176,8 +182,15 @@ function normalizeMaxSteps(value: number | undefined): number | undefined {
|
|
|
176
182
|
return value;
|
|
177
183
|
}
|
|
178
184
|
|
|
185
|
+
function normalizeAnthropicBaseURL(baseURL: string): string {
|
|
186
|
+
const normalized = baseURL.trim().replace(/\/+$/, "");
|
|
187
|
+
return normalized.endsWith("/v1") ? normalized : `${normalized}/v1`;
|
|
188
|
+
}
|
|
189
|
+
|
|
179
190
|
export interface ChatSessionConfig {
|
|
180
|
-
/**
|
|
191
|
+
/** API protocol/provider. Defaults to DEEPCCC_PROVIDER/config, then openai. */
|
|
192
|
+
provider?: DeepCccProvider;
|
|
193
|
+
/** Provider service base URL. Defaults to DEEPCCC_BASE_URL/config. */
|
|
181
194
|
baseURL?: string;
|
|
182
195
|
/** API key. Defaults to DEEPCCC_API_KEY/config. */
|
|
183
196
|
apiKey?: string;
|
|
@@ -254,6 +267,7 @@ interface ChatMessage {
|
|
|
254
267
|
|
|
255
268
|
export class ChatSession {
|
|
256
269
|
private model: any;
|
|
270
|
+
private provider: DeepCccProvider;
|
|
257
271
|
private cwd: string;
|
|
258
272
|
private context: BuiltinContextManager;
|
|
259
273
|
private compactionTimeoutMs: number;
|
|
@@ -278,15 +292,24 @@ export class ChatSession {
|
|
|
278
292
|
|
|
279
293
|
const baseURL = overrides.baseURL ?? appConfig.baseURL;
|
|
280
294
|
const modelId = overrides.model ?? appConfig.model;
|
|
295
|
+
this.provider = normalizeDeepCccProvider(overrides.provider ?? appConfig.provider);
|
|
281
296
|
this.effort = (overrides.effort ?? appConfig.effort ?? "").trim();
|
|
282
297
|
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
298
|
+
if (this.provider === "anthropic") {
|
|
299
|
+
const provider = createAnthropic({
|
|
300
|
+
baseURL: normalizeAnthropicBaseURL(baseURL),
|
|
301
|
+
apiKey,
|
|
302
|
+
});
|
|
303
|
+
this.model = provider(modelId);
|
|
304
|
+
} else {
|
|
305
|
+
const provider = createOpenAICompatible({
|
|
306
|
+
name: "deepccc",
|
|
307
|
+
baseURL,
|
|
308
|
+
apiKey,
|
|
309
|
+
includeUsage: true,
|
|
310
|
+
});
|
|
311
|
+
this.model = provider(modelId);
|
|
312
|
+
}
|
|
290
313
|
this.cwd = options.cwd ?? process.cwd();
|
|
291
314
|
this.maxSteps = normalizeMaxSteps(options.maxSteps);
|
|
292
315
|
this.compactionTimeoutMs = Math.max(1, options.compactionTimeoutMs ?? DEFAULT_COMPACTION_TIMEOUT_MS);
|
|
@@ -384,27 +407,29 @@ export class ChatSession {
|
|
|
384
407
|
const skills = await scanSkillsDirs(this.skillDirs);
|
|
385
408
|
const system = this.buildSystemPrompt(skills);
|
|
386
409
|
this.systemPrompt = system;
|
|
387
|
-
const generationOptions = {
|
|
388
|
-
model: this.model,
|
|
389
|
-
system,
|
|
390
|
-
messages: this.context.buildModelMessages() as any,
|
|
410
|
+
const generationOptions = {
|
|
411
|
+
model: this.model,
|
|
412
|
+
system,
|
|
413
|
+
messages: this.context.buildModelMessages() as any,
|
|
391
414
|
tools: createBuiltinFileTools(this.cwd, { permissionGate: this.permissionGate }),
|
|
392
415
|
stopWhen: maxSteps !== undefined ? stepCountIs(maxSteps) : isLoopFinished(),
|
|
393
416
|
abortSignal: signal,
|
|
394
|
-
// DeepSeek OpenAI 兼容接口:providerOptions.deepseek.reasoningEffort
|
|
395
|
-
// 由 @ai-sdk/openai-compatible 自动映射为请求体 reasoning_effort 字段
|
|
396
|
-
...(this.
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
417
|
+
// DeepSeek OpenAI 兼容接口:providerOptions.deepseek.reasoningEffort
|
|
418
|
+
// 由 @ai-sdk/openai-compatible 自动映射为请求体 reasoning_effort 字段
|
|
419
|
+
...(this.provider === "openai" && this.effort
|
|
420
|
+
? { providerOptions: { deepseek: { reasoningEffort: this.effort } } }
|
|
421
|
+
: {}),
|
|
422
|
+
};
|
|
423
|
+
let stream: AsyncIterable<TextStreamPart<any>>;
|
|
424
|
+
if (appConfig.streaming) {
|
|
425
|
+
const result = streamText(generationOptions);
|
|
426
|
+
stream = result.fullStream ?? textStreamToFullStream(result.textStream);
|
|
427
|
+
} else {
|
|
428
|
+
const result = await generateText(generationOptions);
|
|
429
|
+
stream = generateResultToFullStream(result);
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
for await (const part of stream as AsyncIterable<TextStreamPart<any>>) {
|
|
408
433
|
rawLog?.writeLine(safeRawStreamJson(part));
|
|
409
434
|
if (part.type === "text-delta") {
|
|
410
435
|
fullText += part.text;
|
|
@@ -562,40 +587,40 @@ export class ChatSession {
|
|
|
562
587
|
}
|
|
563
588
|
}
|
|
564
589
|
|
|
565
|
-
async function* textStreamToFullStream(stream: AsyncIterable<string>): AsyncIterable<{ type: "text-delta"; text: string }> {
|
|
566
|
-
for await (const text of stream) {
|
|
567
|
-
yield { type: "text-delta", text };
|
|
568
|
-
}
|
|
569
|
-
}
|
|
570
|
-
|
|
571
|
-
async function* generateResultToFullStream(result: any): AsyncIterable<TextStreamPart<any>> {
|
|
572
|
-
let emittedText = false;
|
|
573
|
-
for (const step of result.steps ?? []) {
|
|
574
|
-
for (const call of step.toolCalls ?? []) {
|
|
575
|
-
yield {
|
|
576
|
-
type: "tool-call",
|
|
577
|
-
toolCallId: call.toolCallId,
|
|
578
|
-
toolName: call.toolName,
|
|
579
|
-
input: call.input,
|
|
580
|
-
} as TextStreamPart<any>;
|
|
581
|
-
}
|
|
582
|
-
for (const toolResult of step.toolResults ?? []) {
|
|
583
|
-
yield {
|
|
584
|
-
type: "tool-result",
|
|
585
|
-
toolCallId: toolResult.toolCallId,
|
|
586
|
-
toolName: toolResult.toolName,
|
|
587
|
-
output: toolResult.output,
|
|
588
|
-
} as TextStreamPart<any>;
|
|
589
|
-
}
|
|
590
|
-
if (step.text) {
|
|
591
|
-
emittedText = true;
|
|
592
|
-
yield { type: "text-delta", text: step.text } as TextStreamPart<any>;
|
|
593
|
-
}
|
|
594
|
-
}
|
|
595
|
-
if (!emittedText && result.text) {
|
|
596
|
-
yield { type: "text-delta", text: result.text } as TextStreamPart<any>;
|
|
597
|
-
}
|
|
598
|
-
}
|
|
590
|
+
async function* textStreamToFullStream(stream: AsyncIterable<string>): AsyncIterable<{ type: "text-delta"; text: string }> {
|
|
591
|
+
for await (const text of stream) {
|
|
592
|
+
yield { type: "text-delta", text };
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
|
|
596
|
+
async function* generateResultToFullStream(result: any): AsyncIterable<TextStreamPart<any>> {
|
|
597
|
+
let emittedText = false;
|
|
598
|
+
for (const step of result.steps ?? []) {
|
|
599
|
+
for (const call of step.toolCalls ?? []) {
|
|
600
|
+
yield {
|
|
601
|
+
type: "tool-call",
|
|
602
|
+
toolCallId: call.toolCallId,
|
|
603
|
+
toolName: call.toolName,
|
|
604
|
+
input: call.input,
|
|
605
|
+
} as TextStreamPart<any>;
|
|
606
|
+
}
|
|
607
|
+
for (const toolResult of step.toolResults ?? []) {
|
|
608
|
+
yield {
|
|
609
|
+
type: "tool-result",
|
|
610
|
+
toolCallId: toolResult.toolCallId,
|
|
611
|
+
toolName: toolResult.toolName,
|
|
612
|
+
output: toolResult.output,
|
|
613
|
+
} as TextStreamPart<any>;
|
|
614
|
+
}
|
|
615
|
+
if (step.text) {
|
|
616
|
+
emittedText = true;
|
|
617
|
+
yield { type: "text-delta", text: step.text } as TextStreamPart<any>;
|
|
618
|
+
}
|
|
619
|
+
}
|
|
620
|
+
if (!emittedText && result.text) {
|
|
621
|
+
yield { type: "text-delta", text: result.text } as TextStreamPart<any>;
|
|
622
|
+
}
|
|
623
|
+
}
|
|
599
624
|
|
|
600
625
|
function safeJson(value: unknown): string {
|
|
601
626
|
try {
|
package/package.json
CHANGED
|
@@ -1,73 +1,74 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "chatccc",
|
|
3
|
-
"version": "0.2.
|
|
4
|
-
"description": "Feishu bot bridge for Claude Code",
|
|
5
|
-
"license": "Apache-2.0",
|
|
6
|
-
"type": "module",
|
|
7
|
-
"main": "./src/index.ts",
|
|
8
|
-
"bin": {
|
|
9
|
-
"chatccc": "bin/chatccc.mjs",
|
|
10
|
-
"cccagent": "bin/cccagent.mjs"
|
|
11
|
-
},
|
|
12
|
-
"files": [
|
|
13
|
-
"src/",
|
|
14
|
-
"deepccc-agent/",
|
|
15
|
-
"bin/",
|
|
16
|
-
"scripts/postinstall-sharp-check.mjs",
|
|
17
|
-
"demo/ilink_echo_probe.ts",
|
|
18
|
-
"agent-prompts/",
|
|
19
|
-
"im-skills/",
|
|
20
|
-
".agents/skills/create-chatccc-feishu-app/",
|
|
21
|
-
".claude/skills/create-chatccc-feishu-app/",
|
|
22
|
-
".cursor/skills/create-chatccc-feishu-app/",
|
|
23
|
-
"images/img_readme_*.jpg",
|
|
24
|
-
"images/img_readme_*.png",
|
|
25
|
-
"images/avatars/status_*.png",
|
|
26
|
-
"images/avatars/badges/",
|
|
27
|
-
"images/avatars/combinations/",
|
|
28
|
-
"package.json",
|
|
29
|
-
"README.md",
|
|
30
|
-
"config.sample.json"
|
|
31
|
-
],
|
|
32
|
-
"scripts": {
|
|
33
|
-
"dev": "tsx src/index.ts",
|
|
34
|
-
"chatccc": "tsx src/index.ts",
|
|
35
|
-
"start": "tsx src/index.ts",
|
|
36
|
-
"demo:bot-test": "tsx demo/bot_test.ts",
|
|
37
|
-
"demo:bot-test:local": "tsx demo/bot_test.ts --local",
|
|
38
|
-
"demo:create-group": "tsx src/index.ts",
|
|
39
|
-
"demo:create-group:local": "tsx src/index.ts --local",
|
|
40
|
-
"demo:permission-check": "tsx demo/permission_check.ts",
|
|
41
|
-
"demo:claude-hi": "tsx demo/claude_say_hi.ts",
|
|
42
|
-
"demo:codex-hi": "tsx demo/codex_say_hi.ts",
|
|
43
|
-
"demo:codex-app-server-approval": "tsx demo/codex-app-server-approval/approval_demo.ts",
|
|
44
|
-
"demo:ilink-echo": "tsx demo/ilink_echo_probe.ts",
|
|
45
|
-
"claude-proxy": "tsx src/litellm-proxy.ts",
|
|
46
|
-
"test": "vitest run",
|
|
47
|
-
"test:deepccc": "vitest run --root deepccc-agent",
|
|
48
|
-
"test:watch": "vitest",
|
|
49
|
-
"postinstall": "node scripts/postinstall-sharp-check.mjs"
|
|
50
|
-
},
|
|
51
|
-
"dependencies": {
|
|
52
|
-
"@ai-sdk/
|
|
53
|
-
"@
|
|
54
|
-
"@
|
|
55
|
-
"@
|
|
56
|
-
"
|
|
57
|
-
"
|
|
58
|
-
"
|
|
59
|
-
"
|
|
60
|
-
"
|
|
61
|
-
"
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
"@types/
|
|
66
|
-
"@types/
|
|
67
|
-
"
|
|
68
|
-
"
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "chatccc",
|
|
3
|
+
"version": "0.2.246",
|
|
4
|
+
"description": "Feishu bot bridge for Claude Code",
|
|
5
|
+
"license": "Apache-2.0",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./src/index.ts",
|
|
8
|
+
"bin": {
|
|
9
|
+
"chatccc": "bin/chatccc.mjs",
|
|
10
|
+
"cccagent": "bin/cccagent.mjs"
|
|
11
|
+
},
|
|
12
|
+
"files": [
|
|
13
|
+
"src/",
|
|
14
|
+
"deepccc-agent/",
|
|
15
|
+
"bin/",
|
|
16
|
+
"scripts/postinstall-sharp-check.mjs",
|
|
17
|
+
"demo/ilink_echo_probe.ts",
|
|
18
|
+
"agent-prompts/",
|
|
19
|
+
"im-skills/",
|
|
20
|
+
".agents/skills/create-chatccc-feishu-app/",
|
|
21
|
+
".claude/skills/create-chatccc-feishu-app/",
|
|
22
|
+
".cursor/skills/create-chatccc-feishu-app/",
|
|
23
|
+
"images/img_readme_*.jpg",
|
|
24
|
+
"images/img_readme_*.png",
|
|
25
|
+
"images/avatars/status_*.png",
|
|
26
|
+
"images/avatars/badges/",
|
|
27
|
+
"images/avatars/combinations/",
|
|
28
|
+
"package.json",
|
|
29
|
+
"README.md",
|
|
30
|
+
"config.sample.json"
|
|
31
|
+
],
|
|
32
|
+
"scripts": {
|
|
33
|
+
"dev": "tsx src/index.ts",
|
|
34
|
+
"chatccc": "tsx src/index.ts",
|
|
35
|
+
"start": "tsx src/index.ts",
|
|
36
|
+
"demo:bot-test": "tsx demo/bot_test.ts",
|
|
37
|
+
"demo:bot-test:local": "tsx demo/bot_test.ts --local",
|
|
38
|
+
"demo:create-group": "tsx src/index.ts",
|
|
39
|
+
"demo:create-group:local": "tsx src/index.ts --local",
|
|
40
|
+
"demo:permission-check": "tsx demo/permission_check.ts",
|
|
41
|
+
"demo:claude-hi": "tsx demo/claude_say_hi.ts",
|
|
42
|
+
"demo:codex-hi": "tsx demo/codex_say_hi.ts",
|
|
43
|
+
"demo:codex-app-server-approval": "tsx demo/codex-app-server-approval/approval_demo.ts",
|
|
44
|
+
"demo:ilink-echo": "tsx demo/ilink_echo_probe.ts",
|
|
45
|
+
"claude-proxy": "tsx src/litellm-proxy.ts",
|
|
46
|
+
"test": "vitest run",
|
|
47
|
+
"test:deepccc": "vitest run --root deepccc-agent",
|
|
48
|
+
"test:watch": "vitest",
|
|
49
|
+
"postinstall": "node scripts/postinstall-sharp-check.mjs"
|
|
50
|
+
},
|
|
51
|
+
"dependencies": {
|
|
52
|
+
"@ai-sdk/anthropic": "^3.0.105",
|
|
53
|
+
"@ai-sdk/openai-compatible": "^2.0.47",
|
|
54
|
+
"@larksuiteoapi/node-sdk": "^1.59.0",
|
|
55
|
+
"@openilink/openilink-sdk-node": "^0.6.0",
|
|
56
|
+
"@vscode/ripgrep": "^1.18.0",
|
|
57
|
+
"ai": "^6.0.184",
|
|
58
|
+
"nodemailer": "^8.0.7",
|
|
59
|
+
"qrcode-terminal": "^0.12.0",
|
|
60
|
+
"sharp": "^0.34.5",
|
|
61
|
+
"tsx": "^4.0.0",
|
|
62
|
+
"ws": "^8.18.0"
|
|
63
|
+
},
|
|
64
|
+
"devDependencies": {
|
|
65
|
+
"@types/node": "^20.0.0",
|
|
66
|
+
"@types/qrcode-terminal": "^0.12.2",
|
|
67
|
+
"@types/ws": "^8.18.1",
|
|
68
|
+
"typescript": "^5.0.0",
|
|
69
|
+
"vitest": "^3.2.4"
|
|
70
|
+
},
|
|
71
|
+
"engines": {
|
|
72
|
+
"node": ">=20"
|
|
73
|
+
}
|
|
74
|
+
}
|