-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathschema.ts
More file actions
114 lines (108 loc) · 2.81 KB
/
Copy pathschema.ts
File metadata and controls
114 lines (108 loc) · 2.81 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/**
* Config schema — SPEC §17 / Appendix F
*
* All fields optional; missing keys inherit from DEFAULT_CONFIG. The loader
* merges CLI > env > ~/.config/agent-tree/config.yaml > <project>/.agent-tree.yaml
* > DEFAULT_CONFIG and validates the result against this schema before use.
*/
export type SidechainHandling = 'include' | 'flatten' | 'drop';
export type LangMode = 'auto' | 'ko' | 'en';
export type LogLevel = 'error' | 'warn' | 'info' | 'debug' | 'trace';
// NOTE: the historical `output.*` and `render.{collapse_depth,node_size_scale,
// default_branch_mode}` keys were removed when the HTML renderer was deleted.
// `render.lang` survives for LLM prompt locale selection.
export interface ClaudeMapConfig {
llm: {
enabled: boolean;
provider: string;
model: string;
max_input_tokens: number;
max_output_tokens: number;
cache: boolean;
parallel: number;
};
redaction: {
enabled: boolean;
strict: boolean;
extra_patterns: string[];
};
render: {
lang: LangMode;
};
analyzer: {
sidechain_handling: SidechainHandling;
topic_gap_minutes: number;
file_jaccard_threshold: number;
};
cache: {
dir: string;
enabled: boolean;
};
log: {
level: LogLevel;
};
telemetry: {
enabled: boolean;
};
}
export const DEFAULT_CONFIG: ClaudeMapConfig = {
llm: {
enabled: true,
provider: 'anthropic',
model: 'claude-sonnet-4-6',
max_input_tokens: 50_000,
max_output_tokens: 5_000,
cache: true,
parallel: 3,
},
redaction: {
enabled: true,
strict: false,
extra_patterns: [],
},
render: {
lang: 'auto',
},
analyzer: {
sidechain_handling: 'include',
topic_gap_minutes: 5,
file_jaccard_threshold: 0.3,
},
cache: {
dir: '~/.cache/agent-tree',
enabled: true,
},
log: {
level: 'info',
},
telemetry: {
enabled: false,
},
};
/**
* Deep-merge `source` into `target`. Objects are merged recursively; arrays
* and primitives are replaced. Returns a fresh copy — neither argument is
* mutated (honors project-wide immutability rule).
*/
export function mergeConfig(
target: ClaudeMapConfig,
source: Partial<ClaudeMapConfig> | undefined | null,
): ClaudeMapConfig {
if (!source) return target;
const out: Record<string, unknown> = { ...(target as unknown as Record<string, unknown>) };
for (const [k, v] of Object.entries(source as Record<string, unknown>)) {
const tv = out[k];
if (isRecord(v) && isRecord(tv)) {
out[k] = mergeConfig(
tv as unknown as ClaudeMapConfig,
v as Partial<ClaudeMapConfig>,
);
} else if (v !== undefined) {
out[k] = v;
}
}
return out as unknown as ClaudeMapConfig;
}
function isRecord(v: unknown): v is Record<string, unknown> {
return typeof v === 'object' && v !== null && !Array.isArray(v);
}