Function bodies 284 total
getDevelopmentConfig function · typescript · L94-L113 (20 LOC)src/utils/logger.ts
function getDevelopmentConfig(): LoggerOptions {
return {
level: getDefaultLogLevel(),
transport: {
target: 'pino-pretty',
options: {
colorize: true,
translateTime: 'SYS:standard',
ignore: 'pid,hostname',
singleLine: false,
messageFormat: '[{context}] {msg}' // Add context prefix if present
}
},
formatters: {
level: (label) => {
return { level: label };
}
}
};
}getProductionConfig function · typescript · L118-L136 (19 LOC)src/utils/logger.ts
function getProductionConfig(): LoggerOptions {
return {
level: getDefaultLogLevel(),
formatters: {
level: (label) => {
return { level: label };
}
},
timestamp: pino.stdTimeFunctions.isoTime,
serializers: {
err: pino.stdSerializers.err,
error: pino.stdSerializers.err
},
base: {
pid: true,
hostname: true
}
};
}setupFileLogging function · typescript · L143-L172 (30 LOC)src/utils/logger.ts
async function setupFileLogging(
logDir: string
): Promise<NodeJS.WritableStream> {
try {
// Create logs directory if it doesn't exist
const logsPath = path.resolve(process.cwd(), logDir);
if (!fs.existsSync(logsPath)) {
fs.mkdirSync(logsPath, { recursive: true });
}
// Dynamic import of pino-roll (no types available)
const pinoRoll = (await import('pino-roll')) as unknown as (file: string, options: unknown) => NodeJS.WritableStream;
// Combined log file with rotation
const logFile = path.join(logsPath, 'disclaude-combined.log');
const rollStream = pinoRoll(logFile, {
size: '10M',
limit: { count: 30 },
compress: true
});
return rollStream;
} catch (error) {
// If pino-roll fails, fall back to stdout
console.warn('Failed to setup file logging, falling back to stdout:', error);
return process.stdout;
}
}createRedactionSerializer function · typescript · L177-L190 (14 LOC)src/utils/logger.ts
function createRedactionSerializer(fields: string[] = SENSITIVE_FIELDS) {
const redactPaths = fields.map((field) => `*.${field}`);
return {
serializers: {
err: pino.stdSerializers.err,
error: pino.stdSerializers.err
},
redact: {
paths: redactPaths,
remove: true
}
};
}initLogger function · typescript · L209-L261 (53 LOC)src/utils/logger.ts
export async function initLogger(config: LoggerConfig = {}): Promise<Logger> {
if (rootLogger) {
return rootLogger;
}
const isDev = isDevelopment();
const logDir = config.logDir ?? process.env.LOG_DIR ?? './logs';
// Get base configuration
let options: LoggerOptions = isDev ? getDevelopmentConfig() : getProductionConfig();
// Override log level if specified
if (config.level) {
options.level = config.level;
}
// Add redaction for sensitive fields
if (!isDev || config.redact) {
const redactConfig = createRedactionSerializer(config.redact);
options = {
...options,
serializers: {
...options.serializers,
...redactConfig.serializers
},
redact: redactConfig.redact
};
}
// Add metadata if provided
if (config.metadata) {
options.base = {
...options.base,
...config.metadata
};
}
// Setup file logging for production or if explicitly requested
let logStream: NodeJS.WritableStreamcreateLogger function · typescript · L288-L307 (20 LOC)src/utils/logger.ts
export function createLogger(
context: string,
metadata?: Record<string, unknown>
): Logger {
// Ensure root logger is initialized
if (!rootLogger) {
// Synchronous initialization for immediate use
const isDev = isDevelopment();
const options = isDev ? getDevelopmentConfig() : getProductionConfig();
rootLogger = pino(options, process.stdout);
}
// Create child logger with context
const childLogger = rootLogger.child({
context,
...metadata
});
return childLogger;
}getRootLogger function · typescript · L316-L323 (8 LOC)src/utils/logger.ts
export function getRootLogger(): Logger {
if (!rootLogger) {
const isDev = isDevelopment();
const options = isDev ? getDevelopmentConfig() : getProductionConfig();
rootLogger = pino(options, process.stdout);
}
return rootLogger;
}Methodology: Repobility · https://repobility.com/research/state-of-ai-code-2026/
flushLogger function · typescript · L353-L361 (9 LOC)src/utils/logger.ts
export function flushLogger(): Promise<void> {
if (rootLogger) {
return new Promise((resolve) => {
// Pino uses async writes, give it time to flush
setTimeout(resolve, 100);
});
}
return Promise.resolve();
}getColorForMessageType function · typescript · L29-L48 (20 LOC)src/utils/output-adapter.ts
function getColorForMessageType(messageType: AgentMessageType): keyof typeof colors {
switch (messageType) {
case 'tool_use':
return 'yellow';
case 'tool_progress':
return 'blue';
case 'tool_result':
return 'cyan';
case 'error':
return 'red';
case 'status':
return 'magenta';
case 'result':
return 'green';
case 'notification':
return 'dim';
default:
return 'reset';
}
}CLIOutputAdapter.write method · typescript · L86-L103 (18 LOC)src/utils/output-adapter.ts
write(content: string, messageType: AgentMessageType = 'text'): void {
// Add newline between different message types
if (messageType !== this.lastMessageType && messageType !== 'text') {
console.log('');
}
// Format and output message
const colorName = getColorForMessageType(messageType);
const formatted = colorText(content, colorName);
process.stdout.write(formatted);
// Add newline for non-text messages
if (messageType !== 'text') {
console.log('');
}
this.lastMessageType = messageType;
}CLIOutputAdapter.finalize method · typescript · L108-L114 (7 LOC)src/utils/output-adapter.ts
finalize(): void {
if (this.lastMessageType !== 'text') {
console.log('');
} else {
console.log('');
}
}FeishuOutputAdapter.constructor method · typescript · L154-L161 (8 LOC)src/utils/output-adapter.ts
constructor(private options: FeishuOutputAdapterOptions) {
this.throttleIntervalMs = options.throttleIntervalMs ?? 2000;
this.fileAttachmentConfig = {
minLines: options.fileAttachment?.minLines ?? 500,
minChars: options.fileAttachment?.minChars ?? 10000,
patterns: options.fileAttachment?.patterns ?? ['*-report.md', 'summary.md', 'analysis-report.md'],
};
}FeishuOutputAdapter.shouldSendProgress method · typescript · L180-L190 (11 LOC)src/utils/output-adapter.ts
private shouldSendProgress(toolName: string): boolean {
const key = `${this.options.chatId}:${toolName}`;
const now = Date.now();
const lastSent = this.progressThrottleMap.get(key);
if (lastSent === undefined || now - lastSent >= this.throttleIntervalMs) {
this.progressThrottleMap.set(key, now);
return true;
}
return false;
}FeishuOutputAdapter.clearThrottleState method · typescript · L195-L201 (7 LOC)src/utils/output-adapter.ts
clearThrottleState(): void {
for (const key of this.progressThrottleMap.keys()) {
if (key.startsWith(`${this.options.chatId}:`)) {
this.progressThrottleMap.delete(key);
}
}
}FeishuOutputAdapter.shouldAutoAttachFile method · typescript · L211-L226 (16 LOC)src/utils/output-adapter.ts
private shouldAutoAttachFile(filePath: string, lineCount: number, charCount: number): boolean {
const fileName = path.basename(filePath);
// Check if file matches any of the configured patterns
const matchesPattern = this.fileAttachmentConfig.patterns.some(pattern => {
// Simple glob matching for *-report.md patterns
const regex = new RegExp(`^${pattern.replace(/\*/g, '.*').replace(/\?/g, '.')}$`);
return regex.test(fileName);
});
// Check thresholds
const exceedsLineThreshold = lineCount >= this.fileAttachmentConfig.minLines;
const exceedsCharThreshold = charCount >= this.fileAttachmentConfig.minChars;
return matchesPattern || exceedsLineThreshold || exceedsCharThreshold;
}Repobility · code-quality intelligence platform · https://repobility.com
FeishuOutputAdapter.write method · typescript · L228-L273 (46 LOC)src/utils/output-adapter.ts
async write(
content: string,
messageType: AgentMessageType = 'text',
metadata?: MessageMetadata
): Promise<void> {
// Skip empty or whitespace-only content
const trimmedContent = content.trim();
if (!trimmedContent) {
return;
}
// Skip SDK completion messages (they create visual noise)
if (messageType === 'result' && trimmedContent.startsWith('✅ Complete')) {
return;
}
// Throttle progress messages
if (messageType === 'tool_progress') {
// Extract tool name from content if possible
const toolMatch = content.match(/Using (\w+):/);
const toolName = toolMatch ? toolMatch[1] : 'unknown';
if (!this.shouldSendProgress(toolName)) {
return; // Skip this message due to throttling
}
}
let cardSent = false;
// Handle Edit tool use with unified diff card
if (messageType === 'tool_use' && metadata?.toolName === 'Edit' && metadata?.toolInputRaw) {
cardSent = await this.senFeishuOutputAdapter.sendEditDiffCard method · typescript · L281-L315 (35 LOC)src/utils/output-adapter.ts
private async sendEditDiffCard(toolInput: Record<string, unknown>): Promise<boolean> {
logger.debug({ keys: Object.keys(toolInput) }, 'Edit tool input keys');
logger.debug({ toolInput }, 'Edit tool input');
try {
// Dynamic import to avoid circular dependencies
const { parseEditToolInput, buildUnifiedDiffCard } = await import('../feishu/diff-card-builder.js');
const codeChange = parseEditToolInput(toolInput);
logger.debug({ success: !!codeChange }, 'Parse edit tool input result');
if (!codeChange) {
logger.debug({
file_path: toolInput.file_path,
filePath: toolInput.filePath,
}, 'File path check');
}
if (codeChange) {
const card = buildUnifiedDiffCard([codeChange], '📝 代码编辑', 'blue');
logger.debug('Card built, sending...');
await this.options.sendCard(this.options.chatId, card);
logger.debug('Card sent successfully');
return true;
}
} catch (erFeishuOutputAdapter.sendWriteContentCard method · typescript · L323-L389 (67 LOC)src/utils/output-adapter.ts
private async sendWriteContentCard(toolInput: Record<string, unknown>): Promise<boolean> {
logger.debug({ keys: Object.keys(toolInput) }, 'Write tool input keys');
logger.debug({ toolInput }, 'Write tool input');
try {
// Dynamic import to avoid circular dependencies
const { parseWriteToolInput, buildWriteContentCard } = await import('../feishu/write-card-builder.js');
const writeContent = parseWriteToolInput(toolInput);
logger.debug({ success: !!writeContent }, 'Parse write tool input result');
if (!writeContent) {
logger.debug({
file_path: toolInput.file_path,
filePath: toolInput.filePath,
}, 'File path check');
}
if (writeContent) {
const card = buildWriteContentCard(writeContent, '✍️ 文件写入', 'green');
logger.debug('Card built, sending...');
await this.options.sendCard(this.options.chatId, card);
logger.debug('Card sent successfully');
// Check if fsafeStringify function · typescript · L31-L38 (8 LOC)src/utils/sdk.ts
function safeStringify(obj: unknown, maxLength: number = 100): string {
try {
const str = JSON.stringify(obj);
return truncate(str, maxLength);
} catch {
return String(obj);
}
}formatToolInput function · typescript · L43-L96 (54 LOC)src/utils/sdk.ts
function formatToolInput(toolName: string, input: Record<string, unknown> | undefined): string {
if (!input) {return '';}
switch (toolName) {
case 'Bash':
const cmd = input.command as string | undefined;
return `Running: ${cmd || '<no command>'}`;
case 'Edit':
const editPath = (input.file_path as string | undefined) || (input.filePath as string | undefined);
return `Editing: ${editPath || '<unknown file>'}`;
case 'Read':
const readPath = input.file_path as string | undefined;
return `Reading: ${readPath || '<unknown file>'}`;
case 'Write': {
const writePath = input.file_path as string | undefined;
const writeContent = input.content as string | undefined;
const lineCount = writeContent ? writeContent.split('\n').length : 0;
return writePath
? `Writing: ${writePath} (${lineCount} lines)`
: 'Writing: <unknown file>';
}
case 'Grep': {
const pattern = input.pattern as string | formatEditToolUse function · typescript · L102-L137 (36 LOC)src/utils/sdk.ts
function formatEditToolUse(input: Record<string, unknown>): string {
// SDK uses snake_case for Edit tool parameters
const filePath = (input.file_path as string | undefined) || (input.filePath as string | undefined);
const oldString = (input.old_string as string | undefined) || (input.oldString as string | undefined);
const newString = (input.new_string as string | undefined) || (input.newString as string | undefined);
if (!filePath) {
return '🔧 Editing: <unknown file>';
}
// Build rich formatted output
const lines: string[] = [];
// Header with file path (cyan for file)
lines.push(`\x1b[36m📝 Editing:\x1b[0m \x1b[1;34m${filePath}\x1b[0m`);
// Show content preview if available
if (oldString !== undefined && newString !== undefined) {
// Truncate long strings for display
const maxPreview = 100;
const oldPreview = oldString.length > maxPreview
? `${oldString.substring(0, maxPreview) }...`
: oldString;
const newPreview = newStrinparseSDKMessage function · typescript · L146-L341 (196 LOC)src/utils/sdk.ts
export function parseSDKMessage(message: SDKMessage): ParsedSDKMessage {
const result: ParsedSDKMessage = {
type: 'text',
content: '',
metadata: {},
};
// Extract session_id from any message that has it
if ('session_id' in message && message.session_id) {
result.sessionId = message.session_id;
}
switch (message.type) {
case 'assistant': {
const apiMessage = message.message;
if (!apiMessage || !Array.isArray(apiMessage.content)) {
return { type: 'text', content: '' };
}
// Check for tool_use blocks in content
const toolBlocks = apiMessage.content.filter(
(block) => block.type === 'tool_use'
);
// Check for text blocks
const textBlocks = apiMessage.content.filter(
(block) => block.type === 'text' && 'text' in block
);
// Accumulate all content blocks (tool uses + text)
const contentParts: string[] = [];
// Process all tool use blocks
for (const blockextractText function · typescript · L353-L370 (18 LOC)src/utils/sdk.ts
export function extractText(message: AgentMessage): string {
const { content } = message;
if (typeof content === 'string') {
return content;
}
if (Array.isArray(content)) {
return content
.filter((block): block is ContentBlock & { text: string } =>
'text' in block && typeof block.text === 'string'
)
.map(block => block.text)
.join('');
}
return '';
}Repobility · code-quality intelligence · https://repobility.com
buildSdkEnv function · typescript · L381-L411 (31 LOC)src/utils/sdk.ts
export function buildSdkEnv(
apiKey: string,
apiBaseUrl?: string,
extraEnv?: Record<string, string | undefined>
): Record<string, string | undefined> {
const nodeBinDir = getNodeBinDir();
const newPath = `${nodeBinDir}:${process.env.PATH || ''}`;
// Priority (highest to lowest):
// 1. Our forced values (API_KEY, PATH, BASE_URL, DEBUG)
// 2. process.env (system environment)
// 3. extraEnv (caller-provided defaults)
// This ensures system env vars can't be accidentally overridden by extraEnv,
// but our critical values always take precedence.
const env: Record<string, string | undefined> = {
...extraEnv,
...(process.env as Record<string, string | undefined>),
ANTHROPIC_API_KEY: apiKey,
PATH: newPath,
// Enable SDK debug logging by default for better troubleshooting
// SDK subprocess errors go to stderr and are critical for debugging
DEBUG_CLAUDE_AGENT_SDK: process.env.DEBUG_CLAUDE_AGENT_SDK ?? '1',
};
// Set base URL if provided (copyDirectory function · typescript · L97-L117 (21 LOC)src/utils/skills-setup.ts
async function copyDirectory(source: string, target: string): Promise<void> {
// Create target directory
await fs.mkdir(target, { recursive: true });
// Read source directory
const entries = await fs.readdir(source, { withFileTypes: true });
// Copy each entry
for (const entry of entries) {
const sourcePath = path.join(source, entry.name);
const targetPath = path.join(target, entry.name);
if (entry.isDirectory()) {
// Recursively copy subdirectory
await copyDirectory(sourcePath, targetPath);
} else {
// Copy file
await fs.copyFile(sourcePath, targetPath);
}
}
}TaskTracker.ensureTasksDir method · typescript · L46-L52 (7 LOC)src/utils/task-tracker.ts
async ensureTasksDir(): Promise<void> {
try {
await fs.mkdir(this.tasksDir, { recursive: true });
} catch (error) {
console.error('Failed to create tasks directory:', error);
}
}TaskTracker.ensureTaskDir method · typescript · L58-L69 (12 LOC)src/utils/task-tracker.ts
private async ensureTaskDir(messageId: string): Promise<string> {
await this.ensureTasksDir();
const sanitized = messageId.replace(/[^a-zA-Z0-9_-]/g, '_');
const taskDir = path.join(this.tasksDir, sanitized);
try {
await fs.mkdir(taskDir, { recursive: true });
return taskDir;
} catch (error) {
console.error(`Failed to create task directory for ${messageId}:`, error);
throw error;
}
}TaskTracker.ensureTaskDirSync method · typescript · L75-L97 (23 LOC)src/utils/task-tracker.ts
private ensureTaskDirSync(messageId: string): string {
const dirExists = syncFs.existsSync(this.tasksDir);
if (!dirExists) {
try {
syncFs.mkdirSync(this.tasksDir, { recursive: true });
} catch (error) {
console.error('Failed to create regular tasks directory:', error);
throw error;
}
}
const sanitized = messageId.replace(/[^a-zA-Z0-9_-]/g, '_');
const taskDir = path.join(this.tasksDir, sanitized);
const taskDirExists = syncFs.existsSync(taskDir);
if (!taskDirExists) {
try {
syncFs.mkdirSync(taskDir, { recursive: true });
} catch (error) {
console.error(`Failed to create task directory for ${messageId}:`, error);
throw error;
}
}
return taskDir;
}TaskTracker.getTaskFilePath method · typescript · L102-L107 (6 LOC)src/utils/task-tracker.ts
getTaskFilePath(messageId: string): string {
// Sanitize message_id to make it a valid filename
// Replace characters that are invalid in filenames
const sanitized = messageId.replace(/[^a-zA-Z0-9_-]/g, '_');
return path.join(this.tasksDir, sanitized, 'task.md');
}TaskTracker.saveTaskRecord method · typescript · L118-L143 (26 LOC)src/utils/task-tracker.ts
async saveTaskRecord(
messageId: string,
metadata: {
chatId: string;
senderType?: string;
senderId?: string;
text: string;
timestamp?: string;
},
content: string
): Promise<void> {
await this.ensureTaskDir(messageId);
const filePath = this.getTaskFilePath(messageId);
const timestamp = metadata.timestamp || new Date().toISOString();
// Use new dialogue format
const markdown = this.formatDialogueTaskRecord(messageId, metadata, content, timestamp);
try {
await fs.writeFile(filePath, markdown, 'utf-8');
console.log(`[Task saved] ${messageId} -> ${filePath}`);
} catch (error) {
console.error(`[Task save failed] ${messageId}:`, error);
}
}TaskTracker.saveTaskRecordSync method · typescript · L153-L179 (27 LOC)src/utils/task-tracker.ts
saveTaskRecordSync(
messageId: string,
metadata: {
chatId: string;
senderType?: string;
senderId?: string;
text: string;
timestamp?: string;
},
content: string
): void {
// Ensure task directory exists synchronously
this.ensureTaskDirSync(messageId);
const filePath = this.getTaskFilePath(messageId);
const timestamp = metadata.timestamp || new Date().toISOString();
// Use new dialogue format
const markdown = this.formatDialogueTaskRecord(messageId, metadata, content, timestamp);
try {
syncFs.writeFileSync(filePath, markdown, 'utf-8');
console.log(`[Task saved sync] ${messageId} -> ${filePath}`);
} catch (error) {
console.error(`[Task save failed] ${messageId}:`, error);
}
}Repobility analyzer · published findings · https://repobility.com
TaskTracker.formatDialogueTaskRecord method · typescript · L185-L214 (30 LOC)src/utils/task-tracker.ts
private formatDialogueTaskRecord(
messageId: string,
metadata: {
chatId: string;
senderType?: string;
senderId?: string;
text: string;
},
_content: string,
timestamp: string
): string {
// Extract title from first line or first 50 chars
const [firstLine] = metadata.text.split('\n');
const title = firstLine.substring(0, 50) + (firstLine.length > 50 ? '...' : '');
return `# Task: ${title}
**Task ID**: ${messageId}
**Created**: ${timestamp}
**Chat ID**: ${metadata.chatId}
**User ID**: ${metadata.senderId || 'N/A'}
${metadata.senderType ? `**Sender Type**: ${metadata.senderType}` : ''}
## Original Request
\`\`\`
${metadata.text}
\`\`\`
`;
}TaskTracker.createDialogueTask method · typescript · L238-L278 (41 LOC)src/utils/task-tracker.ts
async createDialogueTask(
messageId: string,
metadata: {
chatId: string;
userId?: string;
text: string;
timestamp?: string;
}
): Promise<string> {
await this.ensureTaskDir(messageId);
const taskPath = this.getDialogueTaskPath(messageId);
const timestamp = metadata.timestamp || new Date().toISOString();
// Extract title from first line or first 50 chars
const [firstLine] = metadata.text.split('\n');
const title = firstLine.substring(0, 50) + (firstLine.length > 50 ? '...' : '');
const content = `# Task: ${title}
**Task ID**: ${messageId}
**Created**: ${timestamp}
**Chat ID**: ${metadata.chatId}
**User ID**: ${metadata.userId || 'N/A'}
## Original Request
\`\`\`
${metadata.text}
\`\`\`
`;
try {
await fs.writeFile(taskPath, content, 'utf-8');
console.log(`[Dialogue task created] ${messageId} -> ${taskPath}`);
return taskPath;
} catch (error) {
console.error(`[Dialogue task creation fTaskTracker.appendTaskDefinition method · typescript · L287-L336 (50 LOC)src/utils/task-tracker.ts
async appendTaskDefinition(
taskPath: string,
details: TaskDefinitionDetails
): Promise<void> {
const existingContent = await fs.readFile(taskPath, 'utf-8');
const appendContent = `
## Task Objectives
### Primary Goal
${details.primary_goal}
### Success Criteria
${details.success_criteria.map(c => `- ${c}`).join('\n')}
### Expected Outcome
${details.expected_outcome}
## Delivery Specifications
### Required Deliverables
${details.deliverables.map(d => `- ${d}`).join('\n')}
${details.format_requirements?.length ? `
### Format Requirements
${details.format_requirements.map(r => `- ${r}`).join('\n')}
` : ''}
${details.constraints?.length ? `
### Constraints
${details.constraints.map(c => `- ${c}`).join('\n')}
` : ''}
## Quality Criteria
${details.quality_criteria.map(q => `- ${q}`).join('\n')}
---
*Task definition generated by Pilot*
*This document serves as a record and will not be modified during execution.*
`;
try {
await fs.writeFile(taskPath, ‹ prevpage 6 / 6