gencode-ai 0.1.1 → 0.1.2
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/.gencode/settings.local.json +7 -0
- package/README.md +11 -11
- package/dist/agent/agent.d.ts +42 -1
- package/dist/agent/agent.d.ts.map +1 -1
- package/dist/agent/agent.js +82 -15
- package/dist/agent/agent.js.map +1 -1
- package/dist/cli/components/App.d.ts +8 -1
- package/dist/cli/components/App.d.ts.map +1 -1
- package/dist/cli/components/App.js +231 -29
- package/dist/cli/components/App.js.map +1 -1
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -1
- package/dist/cli/components/CommandSuggestions.js +2 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -1
- package/dist/cli/components/Header.d.ts +1 -1
- package/dist/cli/components/Header.d.ts.map +1 -1
- package/dist/cli/components/Header.js +4 -6
- package/dist/cli/components/Header.js.map +1 -1
- package/dist/cli/components/Logo.d.ts +1 -0
- package/dist/cli/components/Logo.d.ts.map +1 -1
- package/dist/cli/components/Logo.js +16 -3
- package/dist/cli/components/Logo.js.map +1 -1
- package/dist/cli/components/Messages.d.ts +4 -4
- package/dist/cli/components/Messages.d.ts.map +1 -1
- package/dist/cli/components/Messages.js +51 -25
- package/dist/cli/components/Messages.js.map +1 -1
- package/dist/cli/components/PermissionPrompt.d.ts +60 -0
- package/dist/cli/components/PermissionPrompt.d.ts.map +1 -0
- package/dist/cli/components/PermissionPrompt.js +192 -0
- package/dist/cli/components/PermissionPrompt.js.map +1 -0
- package/dist/cli/components/ProviderManager.js +3 -3
- package/dist/cli/components/ProviderManager.js.map +1 -1
- package/dist/cli/components/Spinner.d.ts +7 -2
- package/dist/cli/components/Spinner.d.ts.map +1 -1
- package/dist/cli/components/Spinner.js +116 -25
- package/dist/cli/components/Spinner.js.map +1 -1
- package/dist/cli/components/TodoList.d.ts +7 -0
- package/dist/cli/components/TodoList.d.ts.map +1 -0
- package/dist/cli/components/TodoList.js +34 -0
- package/dist/cli/components/TodoList.js.map +1 -0
- package/dist/cli/components/index.d.ts +1 -0
- package/dist/cli/components/index.d.ts.map +1 -1
- package/dist/cli/components/index.js +1 -0
- package/dist/cli/components/index.js.map +1 -1
- package/dist/cli/index.js +47 -7
- package/dist/cli/index.js.map +1 -1
- package/dist/config/index.d.ts +13 -4
- package/dist/config/index.d.ts.map +1 -1
- package/dist/config/index.js +18 -3
- package/dist/config/index.js.map +1 -1
- package/dist/config/levels.d.ts +49 -0
- package/dist/config/levels.d.ts.map +1 -0
- package/dist/config/levels.js +222 -0
- package/dist/config/levels.js.map +1 -0
- package/dist/config/loader.d.ts +46 -0
- package/dist/config/loader.d.ts.map +1 -0
- package/dist/config/loader.js +153 -0
- package/dist/config/loader.js.map +1 -0
- package/dist/config/manager.d.ts +115 -15
- package/dist/config/manager.d.ts.map +1 -1
- package/dist/config/manager.js +260 -34
- package/dist/config/manager.js.map +1 -1
- package/dist/config/manager.test.d.ts +5 -0
- package/dist/config/manager.test.d.ts.map +1 -0
- package/dist/config/manager.test.js +192 -0
- package/dist/config/manager.test.js.map +1 -0
- package/dist/config/merger.d.ts +56 -0
- package/dist/config/merger.d.ts.map +1 -0
- package/dist/config/merger.js +177 -0
- package/dist/config/merger.js.map +1 -0
- package/dist/config/test-utils.d.ts +24 -0
- package/dist/config/test-utils.d.ts.map +1 -0
- package/dist/config/test-utils.js +55 -0
- package/dist/config/test-utils.js.map +1 -0
- package/dist/config/types.d.ts +78 -9
- package/dist/config/types.d.ts.map +1 -1
- package/dist/config/types.js +52 -2
- package/dist/config/types.js.map +1 -1
- package/dist/memory/import-resolver.d.ts +46 -0
- package/dist/memory/import-resolver.d.ts.map +1 -0
- package/dist/memory/import-resolver.js +117 -0
- package/dist/memory/import-resolver.js.map +1 -0
- package/dist/memory/index.d.ts +7 -6
- package/dist/memory/index.d.ts.map +1 -1
- package/dist/memory/index.js +7 -5
- package/dist/memory/index.js.map +1 -1
- package/dist/memory/init-prompt.d.ts +22 -0
- package/dist/memory/init-prompt.d.ts.map +1 -0
- package/dist/memory/init-prompt.js +103 -0
- package/dist/memory/init-prompt.js.map +1 -0
- package/dist/memory/memory-manager.d.ts +119 -0
- package/dist/memory/memory-manager.d.ts.map +1 -0
- package/dist/memory/memory-manager.js +587 -0
- package/dist/memory/memory-manager.js.map +1 -0
- package/dist/memory/rules-parser.d.ts +38 -0
- package/dist/memory/rules-parser.d.ts.map +1 -0
- package/dist/memory/rules-parser.js +69 -0
- package/dist/memory/rules-parser.js.map +1 -0
- package/dist/memory/test-utils.d.ts +20 -0
- package/dist/memory/test-utils.d.ts.map +1 -0
- package/dist/memory/test-utils.js +44 -0
- package/dist/memory/test-utils.js.map +1 -0
- package/dist/memory/types.d.ts +70 -63
- package/dist/memory/types.d.ts.map +1 -1
- package/dist/memory/types.js +42 -2
- package/dist/memory/types.js.map +1 -1
- package/dist/permissions/audit.d.ts +82 -0
- package/dist/permissions/audit.d.ts.map +1 -0
- package/dist/permissions/audit.js +229 -0
- package/dist/permissions/audit.js.map +1 -0
- package/dist/permissions/index.d.ts +11 -1
- package/dist/permissions/index.d.ts.map +1 -1
- package/dist/permissions/index.js +15 -0
- package/dist/permissions/index.js.map +1 -1
- package/dist/permissions/manager.d.ts +149 -13
- package/dist/permissions/manager.d.ts.map +1 -1
- package/dist/permissions/manager.js +480 -35
- package/dist/permissions/manager.js.map +1 -1
- package/dist/permissions/manager.test.d.ts +5 -0
- package/dist/permissions/manager.test.d.ts.map +1 -0
- package/dist/permissions/manager.test.js +213 -0
- package/dist/permissions/manager.test.js.map +1 -0
- package/dist/permissions/persistence.d.ts +74 -0
- package/dist/permissions/persistence.d.ts.map +1 -0
- package/dist/permissions/persistence.js +248 -0
- package/dist/permissions/persistence.js.map +1 -0
- package/dist/permissions/persistence.test.d.ts +5 -0
- package/dist/permissions/persistence.test.d.ts.map +1 -0
- package/dist/permissions/persistence.test.js +171 -0
- package/dist/permissions/persistence.test.js.map +1 -0
- package/dist/permissions/prompt-matcher.d.ts +64 -0
- package/dist/permissions/prompt-matcher.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.js +415 -0
- package/dist/permissions/prompt-matcher.js.map +1 -0
- package/dist/permissions/prompt-matcher.test.d.ts +5 -0
- package/dist/permissions/prompt-matcher.test.d.ts.map +1 -0
- package/dist/permissions/prompt-matcher.test.js +107 -0
- package/dist/permissions/prompt-matcher.test.js.map +1 -0
- package/dist/permissions/types.d.ts +157 -0
- package/dist/permissions/types.d.ts.map +1 -1
- package/dist/permissions/types.js +43 -8
- package/dist/permissions/types.js.map +1 -1
- package/dist/prompts/index.d.ts +92 -0
- package/dist/prompts/index.d.ts.map +1 -0
- package/dist/prompts/index.js +241 -0
- package/dist/prompts/index.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -1
- package/dist/tools/builtin/bash.js +2 -1
- package/dist/tools/builtin/bash.js.map +1 -1
- package/dist/tools/builtin/edit.d.ts.map +1 -1
- package/dist/tools/builtin/edit.js +2 -1
- package/dist/tools/builtin/edit.js.map +1 -1
- package/dist/tools/builtin/glob.d.ts.map +1 -1
- package/dist/tools/builtin/glob.js +2 -1
- package/dist/tools/builtin/glob.js.map +1 -1
- package/dist/tools/builtin/grep.d.ts.map +1 -1
- package/dist/tools/builtin/grep.js +2 -1
- package/dist/tools/builtin/grep.js.map +1 -1
- package/dist/tools/builtin/read.d.ts.map +1 -1
- package/dist/tools/builtin/read.js +2 -1
- package/dist/tools/builtin/read.js.map +1 -1
- package/dist/tools/builtin/todowrite.d.ts +15 -0
- package/dist/tools/builtin/todowrite.d.ts.map +1 -0
- package/dist/tools/builtin/todowrite.js +88 -0
- package/dist/tools/builtin/todowrite.js.map +1 -0
- package/dist/tools/builtin/webfetch.d.ts.map +1 -1
- package/dist/tools/builtin/webfetch.js +2 -5
- package/dist/tools/builtin/webfetch.js.map +1 -1
- package/dist/tools/builtin/websearch.d.ts.map +1 -1
- package/dist/tools/builtin/websearch.js +2 -16
- package/dist/tools/builtin/websearch.js.map +1 -1
- package/dist/tools/builtin/write.d.ts.map +1 -1
- package/dist/tools/builtin/write.js +2 -1
- package/dist/tools/builtin/write.js.map +1 -1
- package/dist/tools/index.d.ts +7 -0
- package/dist/tools/index.d.ts.map +1 -1
- package/dist/tools/index.js +4 -0
- package/dist/tools/index.js.map +1 -1
- package/dist/tools/types.d.ts +22 -0
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/types.js +8 -0
- package/dist/tools/types.js.map +1 -1
- package/docs/config-system-comparison.md +707 -0
- package/docs/memory-system.md +238 -0
- package/docs/permissions.md +368 -0
- package/docs/proposals/0005-todo-system.md +350 -85
- package/docs/proposals/0006-memory-system.md +11 -10
- package/docs/proposals/0012-ask-user-question.md +941 -206
- package/docs/proposals/0023-permission-enhancements.md +61 -2
- package/docs/proposals/0041-configuration-system.md +33 -2
- package/docs/proposals/0042-prompt-optimization.md +866 -0
- package/docs/proposals/README.md +6 -5
- package/jest.config.js +26 -0
- package/package.json +8 -2
- package/src/agent/agent.ts +111 -16
- package/src/cli/components/App.tsx +309 -36
- package/src/cli/components/CommandSuggestions.tsx +2 -0
- package/src/cli/components/Header.tsx +11 -17
- package/src/cli/components/Logo.tsx +76 -9
- package/src/cli/components/Messages.tsx +73 -53
- package/src/cli/components/PermissionPrompt.tsx +388 -0
- package/src/cli/components/ProviderManager.tsx +5 -5
- package/src/cli/components/Spinner.tsx +138 -25
- package/src/cli/components/TodoList.tsx +54 -0
- package/src/cli/components/index.ts +6 -0
- package/src/cli/index.tsx +54 -6
- package/src/config/index.ts +78 -4
- package/src/config/levels.test.ts +163 -0
- package/src/config/levels.ts +285 -0
- package/src/config/loader.test.ts +120 -0
- package/src/config/loader.ts +178 -0
- package/src/config/manager.test.ts +215 -0
- package/src/config/manager.ts +328 -40
- package/src/config/merger.test.ts +360 -0
- package/src/config/merger.ts +221 -0
- package/src/config/test-utils.ts +79 -0
- package/src/config/types.ts +152 -9
- package/src/memory/import-resolver.test.ts +117 -0
- package/src/memory/import-resolver.ts +149 -0
- package/src/memory/index.ts +11 -0
- package/src/memory/init-prompt.ts +113 -0
- package/src/memory/memory-manager.test.ts +198 -0
- package/src/memory/memory-manager.ts +716 -0
- package/src/memory/rules-parser.test.ts +182 -0
- package/src/memory/rules-parser.ts +82 -0
- package/src/memory/test-utils.ts +60 -0
- package/src/memory/types.ts +119 -0
- package/src/permissions/audit.ts +284 -0
- package/src/permissions/index.ts +20 -1
- package/src/permissions/manager.test.ts +260 -0
- package/src/permissions/manager.ts +592 -40
- package/src/permissions/persistence.test.ts +220 -0
- package/src/permissions/persistence.ts +301 -0
- package/src/permissions/prompt-matcher.test.ts +213 -0
- package/src/permissions/prompt-matcher.ts +472 -0
- package/src/permissions/types.ts +236 -8
- package/src/prompts/index.test.ts +279 -0
- package/src/prompts/index.ts +306 -0
- package/src/prompts/system/anthropic.txt +29 -0
- package/src/prompts/system/base.txt +124 -0
- package/src/prompts/system/gemini.txt +35 -0
- package/src/prompts/system/generic.txt +128 -0
- package/src/prompts/system/openai.txt +29 -0
- package/src/prompts/tools/bash.txt +60 -0
- package/src/prompts/tools/edit.txt +29 -0
- package/src/prompts/tools/glob.txt +35 -0
- package/src/prompts/tools/grep.txt +43 -0
- package/src/prompts/tools/read.txt +22 -0
- package/src/prompts/tools/todowrite.txt +71 -0
- package/src/prompts/tools/webfetch.txt +34 -0
- package/src/prompts/tools/websearch.txt +41 -0
- package/src/prompts/tools/write.txt +23 -0
- package/src/tools/builtin/bash.ts +2 -1
- package/src/tools/builtin/edit.ts +2 -1
- package/src/tools/builtin/glob.ts +2 -1
- package/src/tools/builtin/grep.ts +2 -1
- package/src/tools/builtin/read.ts +2 -1
- package/src/tools/builtin/todowrite.ts +102 -0
- package/src/tools/builtin/webfetch.ts +2 -5
- package/src/tools/builtin/websearch.ts +2 -16
- package/src/tools/builtin/write.ts +2 -1
- package/src/tools/index.ts +4 -0
- package/src/tools/types.ts +12 -0
- package/tsconfig.json +1 -1
package/src/permissions/types.ts
CHANGED
|
@@ -1,29 +1,257 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Permission System Types
|
|
3
|
+
* Enhanced permission management with pattern matching, prompt-based approvals,
|
|
4
|
+
* persistence, and audit logging - Claude Code compatible design.
|
|
3
5
|
*/
|
|
4
6
|
|
|
7
|
+
// ============================================================================
|
|
8
|
+
// Core Types
|
|
9
|
+
// ============================================================================
|
|
10
|
+
|
|
5
11
|
export type PermissionMode = 'auto' | 'confirm' | 'deny';
|
|
12
|
+
export type PermissionScope = 'session' | 'project' | 'global';
|
|
13
|
+
export type ApprovalAction = 'allow_once' | 'allow_session' | 'allow_always' | 'deny';
|
|
14
|
+
|
|
15
|
+
// ============================================================================
|
|
16
|
+
// Permission Rules
|
|
17
|
+
// ============================================================================
|
|
6
18
|
|
|
19
|
+
/**
|
|
20
|
+
* Permission rule for matching tool operations
|
|
21
|
+
* Claude Code style: "Bash(git add:*)"
|
|
22
|
+
*/
|
|
7
23
|
export interface PermissionRule {
|
|
24
|
+
/** Tool name or regex pattern */
|
|
8
25
|
tool: string | RegExp;
|
|
26
|
+
/** Permission mode for matched operations */
|
|
9
27
|
mode: PermissionMode;
|
|
28
|
+
/** Optional input pattern for matching (glob-style, e.g., "git add:*") */
|
|
29
|
+
pattern?: string | RegExp;
|
|
30
|
+
/** Semantic description for prompt-based matching */
|
|
31
|
+
prompt?: string;
|
|
32
|
+
/** Rule scope - where this rule applies */
|
|
33
|
+
scope?: PermissionScope;
|
|
34
|
+
/** Expiration timestamp for time-limited rules */
|
|
35
|
+
expiresAt?: Date;
|
|
36
|
+
/** Human-readable description of the rule */
|
|
37
|
+
description?: string;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Prompt-based permission (Claude Code ExitPlanMode style)
|
|
42
|
+
* { tool: "Bash", prompt: "run tests" }
|
|
43
|
+
*/
|
|
44
|
+
export interface PromptPermission {
|
|
45
|
+
/** Tool this permission applies to */
|
|
46
|
+
tool: string;
|
|
47
|
+
/** Semantic description of allowed action */
|
|
48
|
+
prompt: string;
|
|
10
49
|
}
|
|
11
50
|
|
|
51
|
+
// ============================================================================
|
|
52
|
+
// Permission Config
|
|
53
|
+
// ============================================================================
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Complete permission configuration
|
|
57
|
+
*/
|
|
12
58
|
export interface PermissionConfig {
|
|
59
|
+
/** Default mode for unmatched tools */
|
|
13
60
|
defaultMode: PermissionMode;
|
|
61
|
+
/** Built-in and user-defined rules */
|
|
14
62
|
rules: PermissionRule[];
|
|
63
|
+
/** Prompt-based permissions (from plan approval) */
|
|
64
|
+
allowedPrompts: PromptPermission[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Serializable permission settings (for settings.json)
|
|
69
|
+
* Claude Code format: { allow: ["Bash(git add:*)"], ask: ["Bash(npm run:*)"], deny: ["Bash(rm -rf:*)"] }
|
|
70
|
+
*/
|
|
71
|
+
export interface PermissionSettings {
|
|
72
|
+
/** Allow patterns - auto-approve matching operations */
|
|
73
|
+
allow?: string[];
|
|
74
|
+
/** Ask patterns - require confirmation for matching operations */
|
|
75
|
+
ask?: string[];
|
|
76
|
+
/** Deny patterns - block matching operations */
|
|
77
|
+
deny?: string[];
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// ============================================================================
|
|
81
|
+
// Permission Context
|
|
82
|
+
// ============================================================================
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Context for permission check
|
|
86
|
+
*/
|
|
87
|
+
export interface PermissionContext {
|
|
88
|
+
/** Tool being executed */
|
|
89
|
+
tool: string;
|
|
90
|
+
/** Tool input/parameters */
|
|
91
|
+
input: unknown;
|
|
92
|
+
/** Current session ID */
|
|
93
|
+
sessionId?: string;
|
|
94
|
+
/** Project path */
|
|
95
|
+
projectPath?: string;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// ============================================================================
|
|
99
|
+
// Permission Decision
|
|
100
|
+
// ============================================================================
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Result of a permission check
|
|
104
|
+
*/
|
|
105
|
+
export interface PermissionDecision {
|
|
106
|
+
/** Whether operation is allowed */
|
|
107
|
+
allowed: boolean;
|
|
108
|
+
/** Reason for the decision */
|
|
109
|
+
reason: string;
|
|
110
|
+
/** Rule that matched (if any) */
|
|
111
|
+
matchedRule?: PermissionRule | PromptPermission;
|
|
112
|
+
/** Whether user confirmation is required */
|
|
113
|
+
requiresConfirmation: boolean;
|
|
114
|
+
/** Suggested approval options */
|
|
115
|
+
suggestions?: ApprovalSuggestion[];
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* Approval option presented to user
|
|
120
|
+
*/
|
|
121
|
+
export interface ApprovalSuggestion {
|
|
122
|
+
/** Action identifier */
|
|
123
|
+
action: ApprovalAction;
|
|
124
|
+
/** User-facing label */
|
|
125
|
+
label: string;
|
|
126
|
+
/** Description of what this option does */
|
|
127
|
+
description?: string;
|
|
128
|
+
/** Keyboard shortcut (e.g., "1", "y") */
|
|
129
|
+
shortcut?: string;
|
|
15
130
|
}
|
|
16
131
|
|
|
132
|
+
// ============================================================================
|
|
133
|
+
// Audit Types
|
|
134
|
+
// ============================================================================
|
|
135
|
+
|
|
136
|
+
export type AuditDecision = 'allowed' | 'denied' | 'confirmed' | 'rejected';
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Audit log entry for permission decisions
|
|
140
|
+
*/
|
|
141
|
+
export interface PermissionAuditEntry {
|
|
142
|
+
/** When the decision was made */
|
|
143
|
+
timestamp: Date;
|
|
144
|
+
/** Tool that was checked */
|
|
145
|
+
tool: string;
|
|
146
|
+
/** Summarized input (not full payload for privacy) */
|
|
147
|
+
inputSummary: string;
|
|
148
|
+
/** Final decision */
|
|
149
|
+
decision: AuditDecision;
|
|
150
|
+
/** Reason for decision */
|
|
151
|
+
reason: string;
|
|
152
|
+
/** Rule that matched (if any) */
|
|
153
|
+
matchedRule?: string;
|
|
154
|
+
/** Session ID */
|
|
155
|
+
sessionId?: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
// ============================================================================
|
|
159
|
+
// Persistence Types
|
|
160
|
+
// ============================================================================
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Persisted rule for permanent storage
|
|
164
|
+
*/
|
|
165
|
+
export interface PersistedRule {
|
|
166
|
+
/** Unique rule ID */
|
|
167
|
+
id: string;
|
|
168
|
+
/** Tool pattern string */
|
|
169
|
+
tool: string;
|
|
170
|
+
/** Input pattern string */
|
|
171
|
+
pattern?: string;
|
|
172
|
+
/** Permission mode */
|
|
173
|
+
mode: PermissionMode;
|
|
174
|
+
/** Rule scope */
|
|
175
|
+
scope: PermissionScope;
|
|
176
|
+
/** When rule was created */
|
|
177
|
+
createdAt: string;
|
|
178
|
+
/** Description */
|
|
179
|
+
description?: string;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
/**
|
|
183
|
+
* Persisted permissions file structure
|
|
184
|
+
*/
|
|
185
|
+
export interface PersistedPermissions {
|
|
186
|
+
/** Version for migration */
|
|
187
|
+
version: number;
|
|
188
|
+
/** Global rules */
|
|
189
|
+
rules: PersistedRule[];
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
// ============================================================================
|
|
193
|
+
// Callback Types
|
|
194
|
+
// ============================================================================
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Confirmation callback with approval options
|
|
198
|
+
*/
|
|
199
|
+
export type ConfirmCallback = (
|
|
200
|
+
tool: string,
|
|
201
|
+
input: unknown,
|
|
202
|
+
suggestions: ApprovalSuggestion[]
|
|
203
|
+
) => Promise<ApprovalAction>;
|
|
204
|
+
|
|
205
|
+
/**
|
|
206
|
+
* Simple yes/no confirmation callback (for backward compatibility)
|
|
207
|
+
*/
|
|
208
|
+
export type SimpleConfirmCallback = (tool: string, input: unknown) => Promise<boolean>;
|
|
209
|
+
|
|
210
|
+
// ============================================================================
|
|
211
|
+
// Default Configuration
|
|
212
|
+
// ============================================================================
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Default permission configuration (Claude Code style)
|
|
216
|
+
* - Read-only tools auto-approved
|
|
217
|
+
* - Write operations require confirmation
|
|
218
|
+
* - Users can configure additional rules in settings.json
|
|
219
|
+
*/
|
|
17
220
|
export const DEFAULT_PERMISSION_CONFIG: PermissionConfig = {
|
|
18
221
|
defaultMode: 'confirm',
|
|
19
222
|
rules: [
|
|
20
|
-
// Read-only tools
|
|
21
|
-
{ tool: 'Read', mode: 'auto' },
|
|
22
|
-
{ tool: 'Glob', mode: 'auto' },
|
|
23
|
-
{ tool: 'Grep', mode: 'auto' },
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
{ tool: '
|
|
27
|
-
{ tool: 'Bash', mode: 'confirm' },
|
|
223
|
+
// Read-only tools - auto-approve (Claude Code behavior)
|
|
224
|
+
{ tool: 'Read', mode: 'auto', description: 'File reading' },
|
|
225
|
+
{ tool: 'Glob', mode: 'auto', description: 'Pattern matching' },
|
|
226
|
+
{ tool: 'Grep', mode: 'auto', description: 'Content search' },
|
|
227
|
+
{ tool: 'LSP', mode: 'auto', description: 'Language server' },
|
|
228
|
+
// Internal state management - auto-approve (no side effects)
|
|
229
|
+
{ tool: 'TodoWrite', mode: 'auto', description: 'Task tracking' },
|
|
28
230
|
],
|
|
231
|
+
allowedPrompts: [],
|
|
29
232
|
};
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Default approval suggestions (Claude Code style)
|
|
236
|
+
* The second option dynamically shows the path context
|
|
237
|
+
*/
|
|
238
|
+
export const DEFAULT_SUGGESTIONS: ApprovalSuggestion[] = [
|
|
239
|
+
{
|
|
240
|
+
action: 'allow_once',
|
|
241
|
+
label: 'Yes',
|
|
242
|
+
description: 'Allow this operation',
|
|
243
|
+
shortcut: '1',
|
|
244
|
+
},
|
|
245
|
+
{
|
|
246
|
+
action: 'allow_always',
|
|
247
|
+
label: "Yes, and don't ask again",
|
|
248
|
+
description: 'Add to project allowlist',
|
|
249
|
+
shortcut: '2',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
action: 'deny',
|
|
253
|
+
label: 'No',
|
|
254
|
+
description: 'Block this operation',
|
|
255
|
+
shortcut: '3',
|
|
256
|
+
},
|
|
257
|
+
];
|
|
@@ -0,0 +1,279 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Prompt System Tests
|
|
3
|
+
*
|
|
4
|
+
* Tests to ensure prompts are correctly loaded and contain key guidance.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { describe, it, expect } from '@jest/globals';
|
|
8
|
+
import {
|
|
9
|
+
loadPrompt,
|
|
10
|
+
loadSystemPrompt,
|
|
11
|
+
buildSystemPrompt,
|
|
12
|
+
buildSystemPromptWithMemory,
|
|
13
|
+
buildSystemPromptForModel,
|
|
14
|
+
mapProviderToPromptType,
|
|
15
|
+
getPromptTypeForModel,
|
|
16
|
+
formatEnvironmentInfo,
|
|
17
|
+
getEnvironmentInfo,
|
|
18
|
+
type ProviderType,
|
|
19
|
+
} from './index.js';
|
|
20
|
+
|
|
21
|
+
describe('Prompt Loader', () => {
|
|
22
|
+
describe('loadPrompt', () => {
|
|
23
|
+
it('should load base.txt from system category', () => {
|
|
24
|
+
const content = loadPrompt('system', 'base');
|
|
25
|
+
expect(content).toContain('GenCode');
|
|
26
|
+
expect(content.length).toBeGreaterThan(100);
|
|
27
|
+
});
|
|
28
|
+
|
|
29
|
+
it('should load provider-specific prompts', () => {
|
|
30
|
+
const providers: ProviderType[] = ['anthropic', 'openai', 'gemini', 'generic'];
|
|
31
|
+
for (const provider of providers) {
|
|
32
|
+
const content = loadPrompt('system', provider);
|
|
33
|
+
expect(content.length).toBeGreaterThan(0);
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('should load tool descriptions', () => {
|
|
38
|
+
const tools = ['read', 'write', 'edit', 'bash', 'glob', 'grep'];
|
|
39
|
+
for (const tool of tools) {
|
|
40
|
+
const content = loadPrompt('tools', tool);
|
|
41
|
+
expect(content.length).toBeGreaterThan(0);
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
describe('loadSystemPrompt', () => {
|
|
47
|
+
it('should concatenate base + provider prompts', () => {
|
|
48
|
+
const prompt = loadSystemPrompt('anthropic');
|
|
49
|
+
|
|
50
|
+
// Should contain base content
|
|
51
|
+
expect(prompt).toContain('GenCode');
|
|
52
|
+
expect(prompt).toContain('# Tone and Style');
|
|
53
|
+
|
|
54
|
+
// Should contain anthropic-specific content
|
|
55
|
+
expect(prompt).toContain('Claude');
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
it('should work for all provider types', () => {
|
|
59
|
+
const providers: ProviderType[] = ['anthropic', 'openai', 'gemini', 'generic'];
|
|
60
|
+
for (const provider of providers) {
|
|
61
|
+
const prompt = loadSystemPrompt(provider);
|
|
62
|
+
expect(prompt).toContain('GenCode');
|
|
63
|
+
expect(prompt.length).toBeGreaterThan(500);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
describe('buildSystemPrompt', () => {
|
|
69
|
+
it('should inject environment info', () => {
|
|
70
|
+
const prompt = buildSystemPrompt('generic', '/tmp/test', true);
|
|
71
|
+
|
|
72
|
+
expect(prompt).toContain('<env>');
|
|
73
|
+
expect(prompt).toContain('Working directory: /tmp/test');
|
|
74
|
+
expect(prompt).toContain('Is directory a git repo: Yes');
|
|
75
|
+
expect(prompt).toContain('Platform:');
|
|
76
|
+
expect(prompt).toContain("Today's date:");
|
|
77
|
+
expect(prompt).toContain('</env>');
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
it('should replace {{ENVIRONMENT}} placeholder', () => {
|
|
81
|
+
const prompt = buildSystemPrompt('generic', '/test');
|
|
82
|
+
expect(prompt).not.toContain('{{ENVIRONMENT}}');
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
describe('buildSystemPromptWithMemory', () => {
|
|
87
|
+
it('should append memory context when provided', () => {
|
|
88
|
+
const memoryContext = '# Project Rules\n- Use TypeScript';
|
|
89
|
+
const prompt = buildSystemPromptWithMemory('generic', '/test', false, memoryContext);
|
|
90
|
+
|
|
91
|
+
expect(prompt).toContain('<claudeMd>');
|
|
92
|
+
expect(prompt).toContain('# Project Rules');
|
|
93
|
+
expect(prompt).toContain('Use TypeScript');
|
|
94
|
+
expect(prompt).toContain('</claudeMd>');
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
it('should not add memory section when context is empty', () => {
|
|
98
|
+
const prompt = buildSystemPromptWithMemory('generic', '/test', false);
|
|
99
|
+
expect(prompt).not.toContain('<claudeMd>');
|
|
100
|
+
});
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
describe('mapProviderToPromptType', () => {
|
|
104
|
+
it('should map known providers correctly', () => {
|
|
105
|
+
expect(mapProviderToPromptType('anthropic')).toBe('anthropic');
|
|
106
|
+
expect(mapProviderToPromptType('openai')).toBe('openai');
|
|
107
|
+
expect(mapProviderToPromptType('gemini')).toBe('gemini');
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
it('should return generic for unknown providers', () => {
|
|
111
|
+
expect(mapProviderToPromptType('unknown')).toBe('generic');
|
|
112
|
+
expect(mapProviderToPromptType('ollama')).toBe('generic');
|
|
113
|
+
});
|
|
114
|
+
});
|
|
115
|
+
|
|
116
|
+
describe('getPromptTypeForModel', () => {
|
|
117
|
+
it('should use fallback provider when model lookup fails', () => {
|
|
118
|
+
// Unknown model with fallback
|
|
119
|
+
expect(getPromptTypeForModel('unknown-model', 'anthropic')).toBe('anthropic');
|
|
120
|
+
expect(getPromptTypeForModel('unknown-model', 'openai')).toBe('openai');
|
|
121
|
+
});
|
|
122
|
+
|
|
123
|
+
it('should return generic when no fallback provided', () => {
|
|
124
|
+
expect(getPromptTypeForModel('unknown-model')).toBe('generic');
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
describe('buildSystemPromptForModel', () => {
|
|
129
|
+
it('should build prompt using fallback provider', () => {
|
|
130
|
+
const prompt = buildSystemPromptForModel(
|
|
131
|
+
'unknown-model',
|
|
132
|
+
'/test',
|
|
133
|
+
false,
|
|
134
|
+
undefined,
|
|
135
|
+
'anthropic'
|
|
136
|
+
);
|
|
137
|
+
|
|
138
|
+
expect(prompt).toContain('GenCode');
|
|
139
|
+
expect(prompt).toContain('Claude');
|
|
140
|
+
});
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
describe('Environment Info', () => {
|
|
144
|
+
it('should generate correct environment info', () => {
|
|
145
|
+
const env = getEnvironmentInfo('/my/project', true);
|
|
146
|
+
|
|
147
|
+
expect(env.cwd).toBe('/my/project');
|
|
148
|
+
expect(env.isGitRepo).toBe(true);
|
|
149
|
+
expect(env.platform).toBe(process.platform);
|
|
150
|
+
expect(env.date).toMatch(/^\d{4}-\d{2}-\d{2}$/);
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it('should format environment info correctly', () => {
|
|
154
|
+
const env = getEnvironmentInfo('/test', false);
|
|
155
|
+
const formatted = formatEnvironmentInfo(env);
|
|
156
|
+
|
|
157
|
+
expect(formatted).toContain('<env>');
|
|
158
|
+
expect(formatted).toContain('Working directory: /test');
|
|
159
|
+
expect(formatted).toContain('Is directory a git repo: No');
|
|
160
|
+
expect(formatted).toContain('</env>');
|
|
161
|
+
});
|
|
162
|
+
});
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
describe('Prompt Content Validation', () => {
|
|
166
|
+
describe('base.txt - Claude Code key guidance', () => {
|
|
167
|
+
let basePrompt: string;
|
|
168
|
+
|
|
169
|
+
beforeAll(() => {
|
|
170
|
+
basePrompt = loadPrompt('system', 'base');
|
|
171
|
+
});
|
|
172
|
+
|
|
173
|
+
it('should contain token minimization guidance', () => {
|
|
174
|
+
expect(basePrompt).toMatch(/minimize output tokens/i);
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
it('should contain CommonMark rendering info', () => {
|
|
178
|
+
expect(basePrompt).toMatch(/CommonMark/i);
|
|
179
|
+
});
|
|
180
|
+
|
|
181
|
+
it('should contain forbidden preamble/postamble phrases', () => {
|
|
182
|
+
expect(basePrompt).toContain('The answer is');
|
|
183
|
+
expect(basePrompt).toContain('Here is the content');
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
it('should contain conciseness guidance', () => {
|
|
187
|
+
expect(basePrompt).toMatch(/concise|fewer than 4 lines/i);
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
it('should contain non-preachy refusal guidance', () => {
|
|
191
|
+
expect(basePrompt).toMatch(/preachy|annoying/i);
|
|
192
|
+
});
|
|
193
|
+
|
|
194
|
+
it('should contain examples', () => {
|
|
195
|
+
expect(basePrompt).toContain('<example>');
|
|
196
|
+
expect(basePrompt).toContain('</example>');
|
|
197
|
+
// Verify at least one simple example
|
|
198
|
+
expect(basePrompt).toMatch(/2 \+ 2[\s\S]*?4/);
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
it('should contain task management section', () => {
|
|
202
|
+
expect(basePrompt).toContain('TodoWrite');
|
|
203
|
+
});
|
|
204
|
+
|
|
205
|
+
it('should contain tool usage policy', () => {
|
|
206
|
+
expect(basePrompt).toContain('Tool Usage');
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
it('should contain environment placeholder', () => {
|
|
210
|
+
expect(basePrompt).toContain('{{ENVIRONMENT}}');
|
|
211
|
+
});
|
|
212
|
+
});
|
|
213
|
+
|
|
214
|
+
describe('generic.txt - standalone comprehensive prompt', () => {
|
|
215
|
+
let genericPrompt: string;
|
|
216
|
+
|
|
217
|
+
beforeAll(() => {
|
|
218
|
+
genericPrompt = loadPrompt('system', 'generic');
|
|
219
|
+
});
|
|
220
|
+
|
|
221
|
+
it('should contain token minimization guidance', () => {
|
|
222
|
+
expect(genericPrompt).toMatch(/minimize output tokens/i);
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
it('should contain tool selection guidelines table', () => {
|
|
226
|
+
expect(genericPrompt).toContain('| Task | Tool |');
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
it('should contain software engineering workflow', () => {
|
|
230
|
+
expect(genericPrompt).toContain('Software Engineering Workflow');
|
|
231
|
+
});
|
|
232
|
+
|
|
233
|
+
it('should contain security guidance', () => {
|
|
234
|
+
expect(genericPrompt).toMatch(/security|secrets/i);
|
|
235
|
+
});
|
|
236
|
+
|
|
237
|
+
it('should contain examples', () => {
|
|
238
|
+
expect(genericPrompt).toContain('<example>');
|
|
239
|
+
const exampleCount = (genericPrompt.match(/<example>/g) || []).length;
|
|
240
|
+
expect(exampleCount).toBeGreaterThanOrEqual(3);
|
|
241
|
+
});
|
|
242
|
+
});
|
|
243
|
+
|
|
244
|
+
describe('Provider-specific prompts', () => {
|
|
245
|
+
it('anthropic.txt should reference Claude capabilities', () => {
|
|
246
|
+
const prompt = loadPrompt('system', 'anthropic');
|
|
247
|
+
expect(prompt).toMatch(/claude|thinking|anthropic/i);
|
|
248
|
+
});
|
|
249
|
+
|
|
250
|
+
it('openai.txt should reference GPT capabilities', () => {
|
|
251
|
+
const prompt = loadPrompt('system', 'openai');
|
|
252
|
+
expect(prompt).toMatch(/gpt|openai|structured/i);
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
it('gemini.txt should reference Gemini capabilities', () => {
|
|
256
|
+
const prompt = loadPrompt('system', 'gemini');
|
|
257
|
+
expect(prompt).toMatch(/gemini|google|multimodal/i);
|
|
258
|
+
});
|
|
259
|
+
});
|
|
260
|
+
});
|
|
261
|
+
|
|
262
|
+
describe('Tool Description Validation', () => {
|
|
263
|
+
const requiredTools = ['read', 'write', 'edit', 'bash', 'glob', 'grep', 'todowrite'];
|
|
264
|
+
|
|
265
|
+
it.each(requiredTools)('should have description for %s tool', (tool) => {
|
|
266
|
+
const description = loadPrompt('tools', tool);
|
|
267
|
+
expect(description.length).toBeGreaterThan(50);
|
|
268
|
+
});
|
|
269
|
+
|
|
270
|
+
it('bash.txt should contain git safety guidance', () => {
|
|
271
|
+
const bash = loadPrompt('tools', 'bash');
|
|
272
|
+
expect(bash).toMatch(/git|commit/i);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
it('todowrite.txt should contain task state guidance', () => {
|
|
276
|
+
const todo = loadPrompt('tools', 'todowrite');
|
|
277
|
+
expect(todo).toMatch(/pending|in_progress|completed/i);
|
|
278
|
+
});
|
|
279
|
+
});
|