@compilr-dev/sdk 0.1.4 → 0.1.6

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.
@@ -0,0 +1,255 @@
1
+ /**
2
+ * System Prompt Builder
3
+ *
4
+ * Assembles system prompt from modules based on current context.
5
+ * Provides ~50% token reduction by only including relevant modules.
6
+ *
7
+ * Git/CWD detection is injectable via SystemPromptContext for non-Node environments.
8
+ * Falls back to execSync detection in Node.js when not provided.
9
+ */
10
+ import { ALL_MODULES, shouldIncludeModule, getEstimatedTokensForConditions, } from './modules.js';
11
+ /**
12
+ * Get git configuration (user.name and user.email).
13
+ * Returns provided overrides, or auto-detects via execSync in Node.js.
14
+ */
15
+ function getGitConfig(context) {
16
+ // Use injected values if provided
17
+ if (context.gitUserName !== undefined && context.gitUserEmail !== undefined) {
18
+ return { userName: context.gitUserName, userEmail: context.gitUserEmail };
19
+ }
20
+ let userName = context.gitUserName ?? '(not set - commits will fail)';
21
+ let userEmail = context.gitUserEmail ?? '(not set - commits will fail)';
22
+ try {
23
+ // Dynamic import to avoid bundler issues in non-Node environments
24
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
25
+ const { execSync } = require('child_process');
26
+ if (context.gitUserName === undefined) {
27
+ try {
28
+ const name = execSync('git config --global user.name', {
29
+ encoding: 'utf8',
30
+ stdio: ['pipe', 'pipe', 'pipe'],
31
+ }).trim();
32
+ if (name)
33
+ userName = name;
34
+ }
35
+ catch {
36
+ // Not configured
37
+ }
38
+ }
39
+ if (context.gitUserEmail === undefined) {
40
+ try {
41
+ const email = execSync('git config --global user.email', {
42
+ encoding: 'utf8',
43
+ stdio: ['pipe', 'pipe', 'pipe'],
44
+ }).trim();
45
+ if (email)
46
+ userEmail = email;
47
+ }
48
+ catch {
49
+ // Not configured
50
+ }
51
+ }
52
+ }
53
+ catch {
54
+ // child_process not available (browser/edge runtime)
55
+ }
56
+ return { userName, userEmail };
57
+ }
58
+ /**
59
+ * Detect if a directory is a git repository.
60
+ * Uses execSync when available; returns false in non-Node environments.
61
+ */
62
+ export function detectGitRepository(cwd) {
63
+ try {
64
+ // Dynamic import to avoid bundler issues in non-Node environments
65
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
66
+ const { execSync } = require('child_process');
67
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
68
+ const { existsSync } = require('fs');
69
+ const dir = cwd ?? process.cwd();
70
+ // Check for .git directory
71
+ if (existsSync(`${dir}/.git`)) {
72
+ return true;
73
+ }
74
+ // Also check via git command (handles worktrees, etc.)
75
+ execSync('git rev-parse --is-inside-work-tree', {
76
+ cwd: dir,
77
+ encoding: 'utf8',
78
+ stdio: ['pipe', 'pipe', 'pipe'],
79
+ });
80
+ return true;
81
+ }
82
+ catch {
83
+ return false;
84
+ }
85
+ }
86
+ /**
87
+ * Replace placeholders in module content
88
+ */
89
+ function replacePlaceholders(content, context) {
90
+ const gitConfig = getGitConfig(context);
91
+ let cwd;
92
+ try {
93
+ cwd = context.cwd ?? process.cwd();
94
+ }
95
+ catch {
96
+ cwd = context.cwd ?? '(unknown)';
97
+ }
98
+ return content
99
+ .replace('{{CWD}}', cwd)
100
+ .replace('{{GIT_USER_NAME}}', gitConfig.userName)
101
+ .replace('{{GIT_USER_EMAIL}}', gitConfig.userEmail);
102
+ }
103
+ /**
104
+ * SystemPromptBuilder - assembles modular system prompts
105
+ */
106
+ export class SystemPromptBuilder {
107
+ context;
108
+ modules;
109
+ constructor(context = {}, modules) {
110
+ // Auto-detect git if not specified
111
+ this.context = {
112
+ ...context,
113
+ hasGit: context.hasGit ?? detectGitRepository(context.cwd),
114
+ };
115
+ this.modules = modules ?? ALL_MODULES;
116
+ }
117
+ /**
118
+ * Update context (e.g., when mode changes)
119
+ */
120
+ setContext(context) {
121
+ this.context = { ...this.context, ...context };
122
+ }
123
+ /**
124
+ * Get current context
125
+ */
126
+ getContext() {
127
+ return { ...this.context };
128
+ }
129
+ /**
130
+ * Build the system prompt based on current context
131
+ */
132
+ build() {
133
+ const includedModules = [];
134
+ const excludedModules = [];
135
+ const parts = [];
136
+ // Process each module
137
+ for (const module of this.modules) {
138
+ if (shouldIncludeModule(module, this.context)) {
139
+ includedModules.push(module.id);
140
+ parts.push(replacePlaceholders(module.content, this.context));
141
+ }
142
+ else {
143
+ // Determine reason for exclusion
144
+ let reason = 'Unknown';
145
+ if (module.conditions?.hasGit && !this.context.hasGit) {
146
+ reason = 'Not a git repository';
147
+ }
148
+ else if (module.conditions?.enableMetaTools && !this.context.enableMetaTools) {
149
+ reason = 'Meta-tools not enabled';
150
+ }
151
+ else if (module.conditions?.modes && this.context.mode) {
152
+ reason = `Mode is ${this.context.mode}, requires ${module.conditions.modes.join('/')}`;
153
+ }
154
+ else if (module.conditions?.hasProject && !this.context.hasProject) {
155
+ reason = 'No active project';
156
+ }
157
+ excludedModules.push({ id: module.id, reason });
158
+ }
159
+ }
160
+ // Join modules with separators
161
+ let prompt = parts.join('\n\n---\n\n');
162
+ // Append meta-tools index if provided
163
+ if (this.context.metaToolsIndex) {
164
+ prompt += `\n\n---\n\n${this.context.metaToolsIndex}`;
165
+ }
166
+ // Append project context if provided
167
+ if (this.context.projectContext) {
168
+ const projectHeader = this.context.projectName
169
+ ? `## Project Context (${this.context.projectName})`
170
+ : '## Project Context';
171
+ prompt += `\n\n---\n\n${projectHeader}\n\nThe following is project-specific context loaded from COMPILR.md:\n\n${this.context.projectContext}`;
172
+ }
173
+ else if (this.context.projectName) {
174
+ prompt += `\n\n---\n\n## Active Project\n\nThe current project is: **${this.context.projectName}**`;
175
+ }
176
+ // Append guided mode context if provided
177
+ if (this.context.guidedModeContext) {
178
+ prompt += `\n\n---\n\n${this.context.guidedModeContext}`;
179
+ }
180
+ // Append plan mode context if provided
181
+ if (this.context.planModeContext) {
182
+ prompt += `\n\n---\n\n${this.context.planModeContext}`;
183
+ }
184
+ // Calculate estimated tokens
185
+ const baseTokens = getEstimatedTokensForConditions(this.context);
186
+ // Rough estimate for appended contexts (4 chars ≈ 1 token)
187
+ const appendedTokens = Math.ceil(((this.context.projectContext?.length ?? 0) +
188
+ (this.context.guidedModeContext?.length ?? 0) +
189
+ (this.context.planModeContext?.length ?? 0) +
190
+ (this.context.metaToolsIndex?.length ?? 0)) /
191
+ 4);
192
+ return {
193
+ prompt,
194
+ includedModules,
195
+ excludedModules,
196
+ estimatedTokens: baseTokens + appendedTokens,
197
+ };
198
+ }
199
+ /**
200
+ * Build and return just the prompt string
201
+ */
202
+ buildPrompt() {
203
+ return this.build().prompt;
204
+ }
205
+ /**
206
+ * Get estimated token count for current context
207
+ */
208
+ getEstimatedTokens() {
209
+ return this.build().estimatedTokens;
210
+ }
211
+ /**
212
+ * Get a summary of what modules will be included/excluded
213
+ */
214
+ getSummary() {
215
+ const result = this.build();
216
+ return {
217
+ included: result.includedModules,
218
+ excluded: result.excludedModules,
219
+ estimatedTokens: result.estimatedTokens,
220
+ };
221
+ }
222
+ }
223
+ /**
224
+ * Convenience function to build a system prompt
225
+ */
226
+ export function buildSystemPrompt(context = {}) {
227
+ const builder = new SystemPromptBuilder(context);
228
+ return builder.buildPrompt();
229
+ }
230
+ /**
231
+ * Get module stats for debugging
232
+ */
233
+ export function getModuleStats() {
234
+ const conditional = ALL_MODULES.filter((m) => m.conditions);
235
+ const always = ALL_MODULES.filter((m) => !m.conditions);
236
+ // Max: all modules
237
+ const maxTokens = getEstimatedTokensForConditions({
238
+ hasGit: true,
239
+ enableMetaTools: true,
240
+ hasProject: true,
241
+ });
242
+ // Min: no conditional modules
243
+ const minTokens = getEstimatedTokensForConditions({
244
+ hasGit: false,
245
+ enableMetaTools: false,
246
+ hasProject: false,
247
+ });
248
+ return {
249
+ totalModules: ALL_MODULES.length,
250
+ conditionalModules: conditional.length,
251
+ alwaysIncludedModules: always.length,
252
+ maxTokens,
253
+ minTokens,
254
+ };
255
+ }
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Modular System Prompt
3
+ *
4
+ * Token-optimized system prompt that only includes relevant modules
5
+ * based on current context (git repo, mode, project, etc.).
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { SystemPromptBuilder, buildSystemPrompt } from '@compilr-dev/sdk';
10
+ *
11
+ * // Simple usage
12
+ * const prompt = buildSystemPrompt({ hasGit: true, enableMetaTools: true });
13
+ *
14
+ * // Builder pattern for more control
15
+ * const builder = new SystemPromptBuilder({ hasGit: true });
16
+ * builder.setContext({ enableMetaTools: true, projectContext: '...' });
17
+ * const result = builder.build();
18
+ * console.log(`Included: ${result.includedModules.join(', ')}`);
19
+ * console.log(`Est. tokens: ${result.estimatedTokens}`);
20
+ *
21
+ * // Injectable context (for non-Node environments)
22
+ * const prompt2 = buildSystemPrompt({
23
+ * hasGit: true,
24
+ * cwd: '/app',
25
+ * gitUserName: 'Alice',
26
+ * gitUserEmail: 'alice@example.com',
27
+ * });
28
+ *
29
+ * // Custom modules
30
+ * const builder2 = new SystemPromptBuilder({}, [STYLE_MODULE, TASK_EXECUTION_MODULE]);
31
+ * ```
32
+ */
33
+ export { SystemPromptBuilder, buildSystemPrompt, detectGitRepository, getModuleStats, type SystemPromptContext, type BuildResult, } from './builder.js';
34
+ export { ALL_MODULES, IDENTITY_MODULE, STYLE_MODULE, TASK_EXECUTION_MODULE, TODO_MANAGEMENT_MODULE, TOOL_USAGE_DIRECT_MODULE, TOOL_USAGE_META_MODULE, DELEGATION_MODULE, GIT_SAFETY_MODULE, SUGGEST_MODULE, IMPORTANT_RULES_MODULE, ENVIRONMENT_MODULE, shouldIncludeModule, getEstimatedTokensForConditions, getTotalEstimatedTokens, type SystemPromptModule, type ModuleConditions, } from './modules.js';
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Modular System Prompt
3
+ *
4
+ * Token-optimized system prompt that only includes relevant modules
5
+ * based on current context (git repo, mode, project, etc.).
6
+ *
7
+ * Usage:
8
+ * ```typescript
9
+ * import { SystemPromptBuilder, buildSystemPrompt } from '@compilr-dev/sdk';
10
+ *
11
+ * // Simple usage
12
+ * const prompt = buildSystemPrompt({ hasGit: true, enableMetaTools: true });
13
+ *
14
+ * // Builder pattern for more control
15
+ * const builder = new SystemPromptBuilder({ hasGit: true });
16
+ * builder.setContext({ enableMetaTools: true, projectContext: '...' });
17
+ * const result = builder.build();
18
+ * console.log(`Included: ${result.includedModules.join(', ')}`);
19
+ * console.log(`Est. tokens: ${result.estimatedTokens}`);
20
+ *
21
+ * // Injectable context (for non-Node environments)
22
+ * const prompt2 = buildSystemPrompt({
23
+ * hasGit: true,
24
+ * cwd: '/app',
25
+ * gitUserName: 'Alice',
26
+ * gitUserEmail: 'alice@example.com',
27
+ * });
28
+ *
29
+ * // Custom modules
30
+ * const builder2 = new SystemPromptBuilder({}, [STYLE_MODULE, TASK_EXECUTION_MODULE]);
31
+ * ```
32
+ */
33
+ export { SystemPromptBuilder, buildSystemPrompt, detectGitRepository, getModuleStats, } from './builder.js';
34
+ export { ALL_MODULES, IDENTITY_MODULE, STYLE_MODULE, TASK_EXECUTION_MODULE, TODO_MANAGEMENT_MODULE, TOOL_USAGE_DIRECT_MODULE, TOOL_USAGE_META_MODULE, DELEGATION_MODULE, GIT_SAFETY_MODULE, SUGGEST_MODULE, IMPORTANT_RULES_MODULE, ENVIRONMENT_MODULE, shouldIncludeModule, getEstimatedTokensForConditions, getTotalEstimatedTokens, } from './modules.js';
@@ -0,0 +1,124 @@
1
+ /**
2
+ * System Prompt Modules
3
+ *
4
+ * Modular system prompt for token optimization.
5
+ * Each module has content and optional conditions for inclusion.
6
+ *
7
+ * Token savings: ~50% reduction on average by only including relevant modules.
8
+ */
9
+ /**
10
+ * Conditions that determine if a module should be included
11
+ */
12
+ export interface ModuleConditions {
13
+ /** Include only if in a git repository */
14
+ hasGit?: boolean;
15
+ /** Include only in these workflow modes */
16
+ modes?: ('flexible' | 'guided' | 'plan')[];
17
+ /** Include only if there's an active project */
18
+ hasProject?: boolean;
19
+ /** Include only if meta-tools are enabled */
20
+ enableMetaTools?: boolean;
21
+ /** Include only if NO role identity is specified (for default identity module) */
22
+ noRoleIdentity?: boolean;
23
+ }
24
+ /**
25
+ * A system prompt module
26
+ */
27
+ export interface SystemPromptModule {
28
+ /** Unique identifier */
29
+ id: string;
30
+ /** Human-readable name */
31
+ name: string;
32
+ /** The actual prompt content */
33
+ content: string;
34
+ /** Conditions for inclusion (empty = always include) */
35
+ conditions?: ModuleConditions;
36
+ /** Estimated token count (for debugging/optimization) */
37
+ estimatedTokens: number;
38
+ }
39
+ /**
40
+ * Default identity module - only included when NO role is specified
41
+ * When a specialized role (pm, arch, qa, etc.) is used, this is skipped
42
+ * and the role's identity is prepended instead.
43
+ */
44
+ export declare const IDENTITY_MODULE: SystemPromptModule;
45
+ /**
46
+ * Style module - always included
47
+ * Defines tone, style, and behavioral guidelines that apply to ALL agents
48
+ */
49
+ export declare const STYLE_MODULE: SystemPromptModule;
50
+ /**
51
+ * Task execution module - always included
52
+ * Defines how to approach coding tasks
53
+ */
54
+ export declare const TASK_EXECUTION_MODULE: SystemPromptModule;
55
+ /**
56
+ * Todo management module - always included
57
+ * Defines how to use the todo_write tool
58
+ */
59
+ export declare const TODO_MANAGEMENT_MODULE: SystemPromptModule;
60
+ /**
61
+ * Tool usage module (direct tools) - always included
62
+ * Lists tools that are always available
63
+ */
64
+ export declare const TOOL_USAGE_DIRECT_MODULE: SystemPromptModule;
65
+ /**
66
+ * Tool usage module (meta-tools) - only if enableMetaTools=true
67
+ * Explains how to use specialized tools via meta-tools
68
+ */
69
+ export declare const TOOL_USAGE_META_MODULE: SystemPromptModule;
70
+ /**
71
+ * Token delegation module - always included
72
+ * CRITICAL for token efficiency - teaches agent to use sub-agents
73
+ */
74
+ export declare const DELEGATION_MODULE: SystemPromptModule;
75
+ /**
76
+ * Git safety module - only if hasGit=true
77
+ * Defines safety rules for git operations
78
+ */
79
+ export declare const GIT_SAFETY_MODULE: SystemPromptModule;
80
+ /**
81
+ * Suggest module - always included
82
+ * Defines how to use the suggest tool
83
+ */
84
+ export declare const SUGGEST_MODULE: SystemPromptModule;
85
+ /**
86
+ * Important rules module - always included
87
+ * Summary of critical rules
88
+ */
89
+ export declare const IMPORTANT_RULES_MODULE: SystemPromptModule;
90
+ /**
91
+ * Environment module - always included
92
+ * Current working directory and git config
93
+ * Note: {{PLACEHOLDERS}} are replaced at runtime
94
+ */
95
+ export declare const ENVIRONMENT_MODULE: SystemPromptModule;
96
+ /**
97
+ * All modules in the order they should appear in the prompt.
98
+ * Modules without conditions are always included.
99
+ */
100
+ export declare const ALL_MODULES: SystemPromptModule[];
101
+ /**
102
+ * Get total estimated tokens for all modules
103
+ */
104
+ export declare function getTotalEstimatedTokens(): number;
105
+ /**
106
+ * Get estimated tokens for modules that match given conditions
107
+ */
108
+ export declare function getEstimatedTokensForConditions(conditions: {
109
+ hasGit?: boolean;
110
+ enableMetaTools?: boolean;
111
+ mode?: 'flexible' | 'guided' | 'plan';
112
+ hasProject?: boolean;
113
+ hasRoleIdentity?: boolean;
114
+ }): number;
115
+ /**
116
+ * Check if a module should be included based on conditions
117
+ */
118
+ export declare function shouldIncludeModule(module: SystemPromptModule, context: {
119
+ hasGit?: boolean;
120
+ enableMetaTools?: boolean;
121
+ mode?: 'flexible' | 'guided' | 'plan';
122
+ hasProject?: boolean;
123
+ hasRoleIdentity?: boolean;
124
+ }): boolean;