cray-code 1.0.0
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 +316 -0
- package/dist/Tool.d.ts +217 -0
- package/dist/Tool.d.ts.map +1 -0
- package/dist/Tool.js +89 -0
- package/dist/Tool.js.map +1 -0
- package/dist/branding/logo.d.ts +8 -0
- package/dist/branding/logo.d.ts.map +1 -0
- package/dist/branding/logo.js +26 -0
- package/dist/branding/logo.js.map +1 -0
- package/dist/branding/theme.d.ts +27 -0
- package/dist/branding/theme.d.ts.map +1 -0
- package/dist/branding/theme.js +28 -0
- package/dist/branding/theme.js.map +1 -0
- package/dist/commands/registry.d.ts +32 -0
- package/dist/commands/registry.d.ts.map +1 -0
- package/dist/commands/registry.js +759 -0
- package/dist/commands/registry.js.map +1 -0
- package/dist/components/MessageView.d.ts +12 -0
- package/dist/components/MessageView.d.ts.map +1 -0
- package/dist/components/MessageView.js +35 -0
- package/dist/components/MessageView.js.map +1 -0
- package/dist/components/PermissionPrompt.d.ts +11 -0
- package/dist/components/PermissionPrompt.d.ts.map +1 -0
- package/dist/components/PermissionPrompt.js +6 -0
- package/dist/components/PermissionPrompt.js.map +1 -0
- package/dist/components/PluginManager.d.ts +27 -0
- package/dist/components/PluginManager.d.ts.map +1 -0
- package/dist/components/PluginManager.js +391 -0
- package/dist/components/PluginManager.js.map +1 -0
- package/dist/components/ThinkingBlock.d.ts +27 -0
- package/dist/components/ThinkingBlock.d.ts.map +1 -0
- package/dist/components/ThinkingBlock.js +29 -0
- package/dist/components/ThinkingBlock.js.map +1 -0
- package/dist/components/ToolCallBlock.d.ts +14 -0
- package/dist/components/ToolCallBlock.d.ts.map +1 -0
- package/dist/components/ToolCallBlock.js +83 -0
- package/dist/components/ToolCallBlock.js.map +1 -0
- package/dist/components/TrustDialog.d.ts +20 -0
- package/dist/components/TrustDialog.d.ts.map +1 -0
- package/dist/components/TrustDialog.js +80 -0
- package/dist/components/TrustDialog.js.map +1 -0
- package/dist/context.d.ts +25 -0
- package/dist/context.d.ts.map +1 -0
- package/dist/context.js +268 -0
- package/dist/context.js.map +1 -0
- package/dist/cray.d.ts +114 -0
- package/dist/cray.d.ts.map +1 -0
- package/dist/cray.js +338 -0
- package/dist/cray.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +122 -0
- package/dist/index.js.map +1 -0
- package/dist/plugins/registry.d.ts +106 -0
- package/dist/plugins/registry.d.ts.map +1 -0
- package/dist/plugins/registry.js +695 -0
- package/dist/plugins/registry.js.map +1 -0
- package/dist/query.d.ts +31 -0
- package/dist/query.d.ts.map +1 -0
- package/dist/query.js +637 -0
- package/dist/query.js.map +1 -0
- package/dist/queryStream.d.ts +36 -0
- package/dist/queryStream.d.ts.map +1 -0
- package/dist/queryStream.js +704 -0
- package/dist/queryStream.js.map +1 -0
- package/dist/screens/ReplScreen.d.ts +22 -0
- package/dist/screens/ReplScreen.d.ts.map +1 -0
- package/dist/screens/ReplScreen.js +763 -0
- package/dist/screens/ReplScreen.js.map +1 -0
- package/dist/services/agentRunner.d.ts +39 -0
- package/dist/services/agentRunner.d.ts.map +1 -0
- package/dist/services/agentRunner.js +115 -0
- package/dist/services/agentRunner.js.map +1 -0
- package/dist/services/compact.d.ts +34 -0
- package/dist/services/compact.d.ts.map +1 -0
- package/dist/services/compact.js +179 -0
- package/dist/services/compact.js.map +1 -0
- package/dist/services/loadPluginCommands.d.ts +55 -0
- package/dist/services/loadPluginCommands.d.ts.map +1 -0
- package/dist/services/loadPluginCommands.js +219 -0
- package/dist/services/loadPluginCommands.js.map +1 -0
- package/dist/services/mcp/index.d.ts +3 -0
- package/dist/services/mcp/index.d.ts.map +1 -0
- package/dist/services/mcp/index.js +3 -0
- package/dist/services/mcp/index.js.map +1 -0
- package/dist/services/mcp/manager.d.ts +24 -0
- package/dist/services/mcp/manager.d.ts.map +1 -0
- package/dist/services/mcp/manager.js +138 -0
- package/dist/services/mcp/manager.js.map +1 -0
- package/dist/services/mcp/types.d.ts +52 -0
- package/dist/services/mcp/types.d.ts.map +1 -0
- package/dist/services/mcp/types.js +5 -0
- package/dist/services/mcp/types.js.map +1 -0
- package/dist/services/memory.d.ts +38 -0
- package/dist/services/memory.d.ts.map +1 -0
- package/dist/services/memory.js +181 -0
- package/dist/services/memory.js.map +1 -0
- package/dist/services/permissionPrompt.d.ts +38 -0
- package/dist/services/permissionPrompt.d.ts.map +1 -0
- package/dist/services/permissionPrompt.js +83 -0
- package/dist/services/permissionPrompt.js.map +1 -0
- package/dist/services/permissions.d.ts +15 -0
- package/dist/services/permissions.d.ts.map +1 -0
- package/dist/services/permissions.js +237 -0
- package/dist/services/permissions.js.map +1 -0
- package/dist/services/sessionStorage.d.ts +51 -0
- package/dist/services/sessionStorage.d.ts.map +1 -0
- package/dist/services/sessionStorage.js +266 -0
- package/dist/services/sessionStorage.js.map +1 -0
- package/dist/setup.d.ts +22 -0
- package/dist/setup.d.ts.map +1 -0
- package/dist/setup.js +160 -0
- package/dist/setup.js.map +1 -0
- package/dist/skills/bundledSkills.d.ts +18 -0
- package/dist/skills/bundledSkills.d.ts.map +1 -0
- package/dist/skills/bundledSkills.js +277 -0
- package/dist/skills/bundledSkills.js.map +1 -0
- package/dist/skills/index.d.ts +4 -0
- package/dist/skills/index.d.ts.map +1 -0
- package/dist/skills/index.js +3 -0
- package/dist/skills/index.js.map +1 -0
- package/dist/skills/loadSkillsDir.d.ts +45 -0
- package/dist/skills/loadSkillsDir.d.ts.map +1 -0
- package/dist/skills/loadSkillsDir.js +233 -0
- package/dist/skills/loadSkillsDir.js.map +1 -0
- package/dist/state/AppState.d.ts +70 -0
- package/dist/state/AppState.d.ts.map +1 -0
- package/dist/state/AppState.js +106 -0
- package/dist/state/AppState.js.map +1 -0
- package/dist/tools/AgentTool.d.ts +62 -0
- package/dist/tools/AgentTool.d.ts.map +1 -0
- package/dist/tools/AgentTool.js +133 -0
- package/dist/tools/AgentTool.js.map +1 -0
- package/dist/tools/AskUserQuestionTool.d.ts +60 -0
- package/dist/tools/AskUserQuestionTool.d.ts.map +1 -0
- package/dist/tools/AskUserQuestionTool.js +52 -0
- package/dist/tools/AskUserQuestionTool.js.map +1 -0
- package/dist/tools/BashTool.d.ts +33 -0
- package/dist/tools/BashTool.d.ts.map +1 -0
- package/dist/tools/BashTool.js +211 -0
- package/dist/tools/BashTool.js.map +1 -0
- package/dist/tools/EditTool.d.ts +24 -0
- package/dist/tools/EditTool.d.ts.map +1 -0
- package/dist/tools/EditTool.js +102 -0
- package/dist/tools/EditTool.js.map +1 -0
- package/dist/tools/GlobTool.d.ts +17 -0
- package/dist/tools/GlobTool.d.ts.map +1 -0
- package/dist/tools/GlobTool.js +65 -0
- package/dist/tools/GlobTool.js.map +1 -0
- package/dist/tools/GrepTool.d.ts +30 -0
- package/dist/tools/GrepTool.d.ts.map +1 -0
- package/dist/tools/GrepTool.js +140 -0
- package/dist/tools/GrepTool.js.map +1 -0
- package/dist/tools/MCPTool.d.ts +24 -0
- package/dist/tools/MCPTool.d.ts.map +1 -0
- package/dist/tools/MCPTool.js +67 -0
- package/dist/tools/MCPTool.js.map +1 -0
- package/dist/tools/NotebookEditTool.d.ts +28 -0
- package/dist/tools/NotebookEditTool.d.ts.map +1 -0
- package/dist/tools/NotebookEditTool.js +213 -0
- package/dist/tools/NotebookEditTool.js.map +1 -0
- package/dist/tools/NotebookReadTool.d.ts +19 -0
- package/dist/tools/NotebookReadTool.d.ts.map +1 -0
- package/dist/tools/NotebookReadTool.js +191 -0
- package/dist/tools/NotebookReadTool.js.map +1 -0
- package/dist/tools/PlanTools.d.ts +17 -0
- package/dist/tools/PlanTools.d.ts.map +1 -0
- package/dist/tools/PlanTools.js +65 -0
- package/dist/tools/PlanTools.js.map +1 -0
- package/dist/tools/ReadTool.d.ts +21 -0
- package/dist/tools/ReadTool.d.ts.map +1 -0
- package/dist/tools/ReadTool.js +202 -0
- package/dist/tools/ReadTool.js.map +1 -0
- package/dist/tools/SkillTool.d.ts +32 -0
- package/dist/tools/SkillTool.d.ts.map +1 -0
- package/dist/tools/SkillTool.js +217 -0
- package/dist/tools/SkillTool.js.map +1 -0
- package/dist/tools/TodoWriteTool.d.ts +35 -0
- package/dist/tools/TodoWriteTool.d.ts.map +1 -0
- package/dist/tools/TodoWriteTool.js +58 -0
- package/dist/tools/TodoWriteTool.js.map +1 -0
- package/dist/tools/WebFetchTool.d.ts +17 -0
- package/dist/tools/WebFetchTool.d.ts.map +1 -0
- package/dist/tools/WebFetchTool.js +97 -0
- package/dist/tools/WebFetchTool.js.map +1 -0
- package/dist/tools/WebSearchTool.d.ts +18 -0
- package/dist/tools/WebSearchTool.d.ts.map +1 -0
- package/dist/tools/WebSearchTool.js +76 -0
- package/dist/tools/WebSearchTool.js.map +1 -0
- package/dist/tools/WriteTool.d.ts +17 -0
- package/dist/tools/WriteTool.d.ts.map +1 -0
- package/dist/tools/WriteTool.js +84 -0
- package/dist/tools/WriteTool.js.map +1 -0
- package/dist/tools/index.d.ts +21 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +20 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools.d.ts +34 -0
- package/dist/tools.d.ts.map +1 -0
- package/dist/tools.js +102 -0
- package/dist/tools.js.map +1 -0
- package/dist/types/events.d.ts +85 -0
- package/dist/types/events.d.ts.map +1 -0
- package/dist/types/events.js +12 -0
- package/dist/types/events.js.map +1 -0
- package/dist/types/index.d.ts +4 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/types/index.js +4 -0
- package/dist/types/index.js.map +1 -0
- package/dist/types/message.d.ts +71 -0
- package/dist/types/message.d.ts.map +1 -0
- package/dist/types/message.js +5 -0
- package/dist/types/message.js.map +1 -0
- package/dist/types/permission.d.ts +56 -0
- package/dist/types/permission.d.ts.map +1 -0
- package/dist/types/permission.js +46 -0
- package/dist/types/permission.js.map +1 -0
- package/dist/types/processUserInput.d.ts +18 -0
- package/dist/types/processUserInput.d.ts.map +1 -0
- package/dist/types/processUserInput.js +8 -0
- package/dist/types/processUserInput.js.map +1 -0
- package/dist/types/tool.d.ts +32 -0
- package/dist/types/tool.d.ts.map +1 -0
- package/dist/types/tool.js +5 -0
- package/dist/types/tool.js.map +1 -0
- package/dist/utils/compactBoundary.d.ts +11 -0
- package/dist/utils/compactBoundary.d.ts.map +1 -0
- package/dist/utils/compactBoundary.js +26 -0
- package/dist/utils/compactBoundary.js.map +1 -0
- package/dist/utils/configStore.d.ts +41 -0
- package/dist/utils/configStore.d.ts.map +1 -0
- package/dist/utils/configStore.js +111 -0
- package/dist/utils/configStore.js.map +1 -0
- package/dist/utils/forkedAgent.d.ts +40 -0
- package/dist/utils/forkedAgent.d.ts.map +1 -0
- package/dist/utils/forkedAgent.js +231 -0
- package/dist/utils/forkedAgent.js.map +1 -0
- package/dist/utils/messages.d.ts +14 -0
- package/dist/utils/messages.d.ts.map +1 -0
- package/dist/utils/messages.js +29 -0
- package/dist/utils/messages.js.map +1 -0
- package/dist/utils/sandbox.d.ts +22 -0
- package/dist/utils/sandbox.d.ts.map +1 -0
- package/dist/utils/sandbox.js +59 -0
- package/dist/utils/sandbox.js.map +1 -0
- package/dist/utils/sideQuestion.d.ts +29 -0
- package/dist/utils/sideQuestion.d.ts.map +1 -0
- package/dist/utils/sideQuestion.js +81 -0
- package/dist/utils/sideQuestion.js.map +1 -0
- package/install.ps1 +86 -0
- package/install.sh +92 -0
- package/package.json +68 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Memory System for Cray Code.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Claude Code's memory/ directory design.
|
|
5
|
+
* Persistent memory stored as markdown files in .cray/memory/:
|
|
6
|
+
* user/ — user preferences, role, knowledge
|
|
7
|
+
* project/ — project decisions, constraints, ongoing work
|
|
8
|
+
* feedback/ — user corrections, confirmed approaches
|
|
9
|
+
* reference/ — pointers to external resources (docs, dashboards, etc.)
|
|
10
|
+
*
|
|
11
|
+
* Memories are auto-injected into the system prompt on each turn.
|
|
12
|
+
*/
|
|
13
|
+
import { existsSync, readFileSync, readdirSync, mkdirSync, writeFileSync, unlinkSync } from 'fs';
|
|
14
|
+
import { join, basename } from 'path';
|
|
15
|
+
import { homedir } from 'os';
|
|
16
|
+
// ─── Directory Resolution ──────────────────────────────────────────
|
|
17
|
+
export function getMemoryDirectories(projectRoot) {
|
|
18
|
+
const dirs = [];
|
|
19
|
+
// Global memory: ~/.cray/memory/
|
|
20
|
+
const globalDir = join(homedir(), '.cray', 'memory');
|
|
21
|
+
if (existsSync(globalDir))
|
|
22
|
+
dirs.push(globalDir);
|
|
23
|
+
// Project memory: <project>/.cray/memory/
|
|
24
|
+
if (projectRoot) {
|
|
25
|
+
const projectDir = join(projectRoot, '.cray', 'memory');
|
|
26
|
+
if (existsSync(projectDir))
|
|
27
|
+
dirs.push(projectDir);
|
|
28
|
+
}
|
|
29
|
+
return dirs;
|
|
30
|
+
}
|
|
31
|
+
function getTypeDir(base, type) {
|
|
32
|
+
return join(base, type);
|
|
33
|
+
}
|
|
34
|
+
// ─── Load All Memories ─────────────────────────────────────────────
|
|
35
|
+
export function loadAllMemories(projectRoot) {
|
|
36
|
+
const dirs = getMemoryDirectories(projectRoot);
|
|
37
|
+
const entries = [];
|
|
38
|
+
for (const dir of dirs) {
|
|
39
|
+
for (const type of ['user', 'project', 'feedback', 'reference']) {
|
|
40
|
+
const typeDir = join(dir, type);
|
|
41
|
+
if (!existsSync(typeDir))
|
|
42
|
+
continue;
|
|
43
|
+
try {
|
|
44
|
+
for (const file of readdirSync(typeDir)) {
|
|
45
|
+
if (!file.endsWith('.md'))
|
|
46
|
+
continue;
|
|
47
|
+
const filePath = join(typeDir, file);
|
|
48
|
+
try {
|
|
49
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
50
|
+
const entry = parseMemoryFile(file, content, filePath, type);
|
|
51
|
+
if (entry)
|
|
52
|
+
entries.push(entry);
|
|
53
|
+
}
|
|
54
|
+
catch { /* skip unreadable */ }
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch { /* skip unreadable dir */ }
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return entries;
|
|
61
|
+
}
|
|
62
|
+
/** Build the memory prompt block injected into system prompt */
|
|
63
|
+
export function buildMemoryPrompt(projectRoot) {
|
|
64
|
+
const entries = loadAllMemories(projectRoot);
|
|
65
|
+
if (entries.length === 0)
|
|
66
|
+
return '';
|
|
67
|
+
// Group by type
|
|
68
|
+
const byType = {};
|
|
69
|
+
for (const e of entries) {
|
|
70
|
+
(byType[e.type] ??= []).push(e);
|
|
71
|
+
}
|
|
72
|
+
const lines = [];
|
|
73
|
+
lines.push('─── Persistent Memory ───');
|
|
74
|
+
lines.push('');
|
|
75
|
+
const labels = {
|
|
76
|
+
user: 'About You (user profile)',
|
|
77
|
+
project: 'Project Context',
|
|
78
|
+
feedback: 'Feedback & Preferences',
|
|
79
|
+
reference: 'External References',
|
|
80
|
+
};
|
|
81
|
+
for (const [type, mems] of Object.entries(byType)) {
|
|
82
|
+
lines.push(`[${labels[type] || type}]`);
|
|
83
|
+
for (const m of mems.slice(0, 5)) {
|
|
84
|
+
lines.push(`- ${m.description}`);
|
|
85
|
+
}
|
|
86
|
+
lines.push('');
|
|
87
|
+
}
|
|
88
|
+
lines.push(`(${entries.length} total memories loaded)`);
|
|
89
|
+
return lines.join('\n');
|
|
90
|
+
}
|
|
91
|
+
/** Build a single memory entry' full content for tool display */
|
|
92
|
+
export function buildMemoryContentPrompt(projectRoot) {
|
|
93
|
+
const entries = loadAllMemories(projectRoot);
|
|
94
|
+
if (entries.length === 0)
|
|
95
|
+
return '';
|
|
96
|
+
const lines = ['MEMORY CONTEXT:', ''];
|
|
97
|
+
for (const e of entries) {
|
|
98
|
+
lines.push(`--- ${e.type}: ${e.name} ---`);
|
|
99
|
+
lines.push(e.content.slice(0, 500));
|
|
100
|
+
lines.push('');
|
|
101
|
+
}
|
|
102
|
+
return lines.join('\n');
|
|
103
|
+
}
|
|
104
|
+
// ─── Save / Create ─────────────────────────────────────────────────
|
|
105
|
+
export function saveMemory(type, name, description, content, projectRoot) {
|
|
106
|
+
const baseDir = projectRoot
|
|
107
|
+
? join(projectRoot, '.cray', 'memory')
|
|
108
|
+
: join(homedir(), '.cray', 'memory');
|
|
109
|
+
const typeDir = join(baseDir, type);
|
|
110
|
+
mkdirSync(typeDir, { recursive: true });
|
|
111
|
+
const safeName = name.replace(/[^a-zA-Z0-9一-鿿_-]/g, '-');
|
|
112
|
+
const filePath = join(typeDir, `${safeName}.md`);
|
|
113
|
+
const frontmatter = [
|
|
114
|
+
'---',
|
|
115
|
+
`name: ${safeName}`,
|
|
116
|
+
`description: ${description}`,
|
|
117
|
+
`type: ${type}`,
|
|
118
|
+
'---',
|
|
119
|
+
'',
|
|
120
|
+
content,
|
|
121
|
+
].join('\n');
|
|
122
|
+
writeFileSync(filePath, frontmatter, 'utf-8');
|
|
123
|
+
return { success: true, message: `Memory "${name}" saved as ${type}.`, path: filePath };
|
|
124
|
+
}
|
|
125
|
+
export function deleteMemory(type, name, projectRoot) {
|
|
126
|
+
const dirs = getMemoryDirectories(projectRoot);
|
|
127
|
+
for (const dir of dirs) {
|
|
128
|
+
const filePath = join(dir, type, `${name}.md`);
|
|
129
|
+
if (existsSync(filePath)) {
|
|
130
|
+
unlinkSync(filePath);
|
|
131
|
+
return { success: true, message: `Memory "${name}" deleted.` };
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return { success: false, message: `Memory "${name}" not found.` };
|
|
135
|
+
}
|
|
136
|
+
export function listMemories(projectRoot) {
|
|
137
|
+
return loadAllMemories(projectRoot);
|
|
138
|
+
}
|
|
139
|
+
// ─── Memory Injection Hint for System Prompt ──────────────────────
|
|
140
|
+
export function getMemoryInjectionHint() {
|
|
141
|
+
return [
|
|
142
|
+
'You have access to a persistent memory system.',
|
|
143
|
+
`Memories are stored in ~/.cray/memory/ and <project>/.cray/memory/.`,
|
|
144
|
+
'Types: user (about the user), project (project context), feedback (preferences), reference (external refs).',
|
|
145
|
+
'When the user says "remember this" or gives feedback about how to work, SAVE IT using the memory tool.',
|
|
146
|
+
'When relevant, recall memories to personalize responses.',
|
|
147
|
+
].join('\n');
|
|
148
|
+
}
|
|
149
|
+
// ─── Parser ───────────────────────────────────────────────────────
|
|
150
|
+
function parseMemoryFile(filename, content, filePath, type) {
|
|
151
|
+
let name = basename(filename, '.md');
|
|
152
|
+
let description = '';
|
|
153
|
+
if (content.startsWith('---')) {
|
|
154
|
+
const endIdx = content.indexOf('---', 3);
|
|
155
|
+
if (endIdx > 0) {
|
|
156
|
+
const fm = content.slice(3, endIdx).trim();
|
|
157
|
+
for (const line of fm.split('\n')) {
|
|
158
|
+
const ci = line.indexOf(':');
|
|
159
|
+
if (ci < 0)
|
|
160
|
+
continue;
|
|
161
|
+
const k = line.slice(0, ci).trim();
|
|
162
|
+
const v = line.slice(ci + 1).trim().replace(/^["']|["']$/g, '');
|
|
163
|
+
if (k === 'name')
|
|
164
|
+
name = v || name;
|
|
165
|
+
if (k === 'description')
|
|
166
|
+
description = v;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
if (!description) {
|
|
171
|
+
description = content
|
|
172
|
+
.replace(/^---[\s\S]*?---/, '')
|
|
173
|
+
.trim()
|
|
174
|
+
.split('\n')
|
|
175
|
+
.find((l) => l.trim() && !l.startsWith('#'))
|
|
176
|
+
?.trim()
|
|
177
|
+
.slice(0, 80) || name;
|
|
178
|
+
}
|
|
179
|
+
return { type, name, description, content, path: filePath };
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=memory.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.js","sourceRoot":"","sources":["../../src/services/memory.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Permission Prompt for Cray Code.
|
|
3
|
+
*
|
|
4
|
+
* When a tool requests permission (behavior: 'ask'), this module
|
|
5
|
+
* renders a Y/N prompt inline in the terminal and waits for the user.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* Y / Yes / y / yes → allow
|
|
9
|
+
* N / No / n / no → deny
|
|
10
|
+
* Enter → deny (default safe)
|
|
11
|
+
* A / a → allow ALL subsequent asks this session
|
|
12
|
+
*
|
|
13
|
+
* Mode 'bypass' skips all prompts.
|
|
14
|
+
* Mode 'acceptEdits' skips write/edit, prompts for bash.
|
|
15
|
+
* Mode 'default' prompts for all destructive operations.
|
|
16
|
+
*/
|
|
17
|
+
export type PromptAnswer = 'allow' | 'deny' | 'allowAll';
|
|
18
|
+
export interface PermissionPromptOptions {
|
|
19
|
+
/** What the tool wants to do */
|
|
20
|
+
message: string;
|
|
21
|
+
/** Current permission mode */
|
|
22
|
+
mode: string;
|
|
23
|
+
/** Whether "allow all" has been set this session */
|
|
24
|
+
allowAllActive: boolean;
|
|
25
|
+
/** Abort signal to cancel the prompt */
|
|
26
|
+
signal?: AbortSignal;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Returns 'allow' | 'deny' | 'allowAll'.
|
|
30
|
+
* Call this from the tool execution layer before running a tool.
|
|
31
|
+
*/
|
|
32
|
+
export declare function askPermission(opts: PermissionPromptOptions): Promise<PromptAnswer>;
|
|
33
|
+
/** Resolve a permission prompt synchronously (used in non-interactive mode). */
|
|
34
|
+
export declare function askPermissionSync(opts: PermissionPromptOptions): PromptAnswer;
|
|
35
|
+
export declare const PERMISSION_MODES: readonly ["default", "acceptEdits", "bypass", "plan"];
|
|
36
|
+
export type PermissionMode = (typeof PERMISSION_MODES)[number];
|
|
37
|
+
export declare function isMode(value: string): value is PermissionMode;
|
|
38
|
+
//# sourceMappingURL=permissionPrompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionPrompt.d.ts","sourceRoot":"","sources":["../../src/services/permissionPrompt.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AAIH,MAAM,MAAM,YAAY,GAAG,OAAO,GAAG,MAAM,GAAG,UAAU,CAAC;AAEzD,MAAM,WAAW,uBAAuB;IACtC,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAC;IAChB,8BAA8B;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,oDAAoD;IACpD,cAAc,EAAE,OAAO,CAAC;IACxB,wCAAwC;IACxC,MAAM,CAAC,EAAE,WAAW,CAAC;CACtB;AAED;;;GAGG;AACH,wBAAsB,aAAa,CAAC,IAAI,EAAE,uBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CA0BxF;AAED,gFAAgF;AAChF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,uBAAuB,GAAG,YAAY,CAI7E;AAsBD,eAAO,MAAM,gBAAgB,uDAAwD,CAAC;AACtF,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,wBAAgB,MAAM,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,cAAc,CAE7D"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive Permission Prompt for Cray Code.
|
|
3
|
+
*
|
|
4
|
+
* When a tool requests permission (behavior: 'ask'), this module
|
|
5
|
+
* renders a Y/N prompt inline in the terminal and waits for the user.
|
|
6
|
+
*
|
|
7
|
+
* Rules:
|
|
8
|
+
* Y / Yes / y / yes → allow
|
|
9
|
+
* N / No / n / no → deny
|
|
10
|
+
* Enter → deny (default safe)
|
|
11
|
+
* A / a → allow ALL subsequent asks this session
|
|
12
|
+
*
|
|
13
|
+
* Mode 'bypass' skips all prompts.
|
|
14
|
+
* Mode 'acceptEdits' skips write/edit, prompts for bash.
|
|
15
|
+
* Mode 'default' prompts for all destructive operations.
|
|
16
|
+
*/
|
|
17
|
+
import readline from 'readline';
|
|
18
|
+
/**
|
|
19
|
+
* Returns 'allow' | 'deny' | 'allowAll'.
|
|
20
|
+
* Call this from the tool execution layer before running a tool.
|
|
21
|
+
*/
|
|
22
|
+
export async function askPermission(opts) {
|
|
23
|
+
if (opts.mode === 'bypass')
|
|
24
|
+
return 'allow';
|
|
25
|
+
if (opts.allowAllActive)
|
|
26
|
+
return 'allow';
|
|
27
|
+
// Write/Edit operations in acceptEdits mode are auto-allowed
|
|
28
|
+
const isFileOp = opts.message.toLowerCase().includes('write') ||
|
|
29
|
+
opts.message.toLowerCase().includes('edit') ||
|
|
30
|
+
opts.message.toLowerCase().includes('create') ||
|
|
31
|
+
opts.message.toLowerCase().includes('overwrite');
|
|
32
|
+
if (opts.mode === 'acceptEdits' && isFileOp)
|
|
33
|
+
return 'allow';
|
|
34
|
+
// Build the prompt
|
|
35
|
+
const text = `\n ⚡ ${opts.message}\n [Y] yes [N] no (default) [A] allow all → `;
|
|
36
|
+
process.stderr.write(text);
|
|
37
|
+
const answer = await readLine(opts.signal);
|
|
38
|
+
process.stderr.write('\n');
|
|
39
|
+
const trimmed = answer.trim().toLowerCase();
|
|
40
|
+
if (trimmed === 'y' || trimmed === 'yes')
|
|
41
|
+
return 'allow';
|
|
42
|
+
if (trimmed === 'a' || trimmed === 'allow' || trimmed === 'allow all')
|
|
43
|
+
return 'allowAll';
|
|
44
|
+
// Default: deny
|
|
45
|
+
return 'deny';
|
|
46
|
+
}
|
|
47
|
+
/** Resolve a permission prompt synchronously (used in non-interactive mode). */
|
|
48
|
+
export function askPermissionSync(opts) {
|
|
49
|
+
if (opts.mode === 'bypass')
|
|
50
|
+
return 'allow';
|
|
51
|
+
if (opts.allowAllActive)
|
|
52
|
+
return 'allow';
|
|
53
|
+
return 'deny'; // non-interactive → safe default
|
|
54
|
+
}
|
|
55
|
+
// ─── Read a single line from stdin ─────────────────────────────────
|
|
56
|
+
function readLine(signal) {
|
|
57
|
+
return new Promise((resolve) => {
|
|
58
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stderr });
|
|
59
|
+
let resolved = false;
|
|
60
|
+
const onSig = () => {
|
|
61
|
+
if (!resolved) {
|
|
62
|
+
resolved = true;
|
|
63
|
+
rl.close();
|
|
64
|
+
resolve('n');
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
signal?.addEventListener('abort', onSig, { once: true });
|
|
68
|
+
rl.question('', (answer) => {
|
|
69
|
+
if (!resolved) {
|
|
70
|
+
resolved = true;
|
|
71
|
+
signal?.removeEventListener('abort', onSig);
|
|
72
|
+
rl.close();
|
|
73
|
+
resolve(answer);
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// ─── Permission Mode Helpers ──────────────────────────────────────
|
|
79
|
+
export const PERMISSION_MODES = ['default', 'acceptEdits', 'bypass', 'plan'];
|
|
80
|
+
export function isMode(value) {
|
|
81
|
+
return PERMISSION_MODES.includes(value);
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=permissionPrompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissionPrompt.js","sourceRoot":"","sources":["../../src/services/permissionPrompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Engine — mirrors Claude Code's utils/permissions/permissions.ts.
|
|
3
|
+
*
|
|
4
|
+
* Core function: hasPermissionsToUseTool()
|
|
5
|
+
* Full pipeline: tool-level deny → tool-level ask → tool.checkPermissions →
|
|
6
|
+
* safety checks → mode bypass → tool-level allow → convert passthrough→ask
|
|
7
|
+
*
|
|
8
|
+
* Post-processing: dontAsk mode, acceptEdits fast-path, headless auto-deny.
|
|
9
|
+
*/
|
|
10
|
+
import type { ToolDef } from '../Tool.js';
|
|
11
|
+
import type { PermissionResult, PermissionRule, ToolPermissionContext, PermissionMode } from '../types/permission.js';
|
|
12
|
+
export declare function hasPermissionsToUseTool(tool: ToolDef<any, any>, input: Record<string, unknown>, context: ToolPermissionContext): Promise<PermissionResult>;
|
|
13
|
+
export declare function addPermissionRule(rule: PermissionRule, context: ToolPermissionContext): ToolPermissionContext;
|
|
14
|
+
export declare function setPermissionMode(mode: PermissionMode, context: ToolPermissionContext): ToolPermissionContext;
|
|
15
|
+
//# sourceMappingURL=permissions.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.d.ts","sourceRoot":"","sources":["../../src/services/permissions.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,YAAY,CAAC;AAC1C,OAAO,KAAK,EACV,gBAAgB,EAChB,cAAc,EACd,qBAAqB,EAGrB,cAAc,EACf,MAAM,wBAAwB,CAAC;AAMhC,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,OAAO,CAAC,GAAG,EAAE,GAAG,CAAC,EACvB,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAC9B,OAAO,EAAE,qBAAqB,GAC7B,OAAO,CAAC,gBAAgB,CAAC,CAG3B;AA4QD,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,GAC7B,qBAAqB,CAcvB;AAED,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,cAAc,EACpB,OAAO,EAAE,qBAAqB,GAC7B,qBAAqB,CASvB"}
|
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Permission Engine — mirrors Claude Code's utils/permissions/permissions.ts.
|
|
3
|
+
*
|
|
4
|
+
* Core function: hasPermissionsToUseTool()
|
|
5
|
+
* Full pipeline: tool-level deny → tool-level ask → tool.checkPermissions →
|
|
6
|
+
* safety checks → mode bypass → tool-level allow → convert passthrough→ask
|
|
7
|
+
*
|
|
8
|
+
* Post-processing: dontAsk mode, acceptEdits fast-path, headless auto-deny.
|
|
9
|
+
*/
|
|
10
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
11
|
+
// MAIN ENTRY POINT
|
|
12
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
13
|
+
export async function hasPermissionsToUseTool(tool, input, context) {
|
|
14
|
+
const inner = await hasPermissionsToUseToolInner(tool, input, context);
|
|
15
|
+
return postProcess(inner, context);
|
|
16
|
+
}
|
|
17
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
18
|
+
// STEP 1: Check tool-level deny
|
|
19
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
20
|
+
function hasPermissionsToUseToolInner(tool, input, context) {
|
|
21
|
+
return checkDenyRules(tool, input, context);
|
|
22
|
+
}
|
|
23
|
+
async function checkDenyRules(tool, input, context) {
|
|
24
|
+
// 1a. Entire tool denied by rule
|
|
25
|
+
const denyRule = getDenyRuleForTool(tool.name, context.alwaysDenyRules);
|
|
26
|
+
if (denyRule) {
|
|
27
|
+
return {
|
|
28
|
+
behavior: 'deny',
|
|
29
|
+
message: `Tool "${tool.name}" is permanently denied by rule.`,
|
|
30
|
+
decisionReason: { type: 'rule', message: `Denied by rule from ${denyRule.source ?? 'settings'}` },
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
// 1b. Content-specific deny: check if input matches a deny pattern
|
|
34
|
+
const contentDeny = matchContentRule(tool.name, input, context.alwaysDenyRules, 'deny');
|
|
35
|
+
if (contentDeny) {
|
|
36
|
+
return {
|
|
37
|
+
behavior: 'deny',
|
|
38
|
+
message: `This specific ${tool.name} operation matches a deny rule.`,
|
|
39
|
+
decisionReason: { type: 'rule', message: contentDeny.message },
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
return checkAskRules(tool, input, context);
|
|
43
|
+
}
|
|
44
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
45
|
+
// STEP 2: Tool-level ask rules
|
|
46
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
47
|
+
async function checkAskRules(tool, input, context) {
|
|
48
|
+
// 2a. Entire tool always ask
|
|
49
|
+
const askRule = context.alwaysAskRules.find((r) => r.toolName === tool.name && !r.pattern);
|
|
50
|
+
if (askRule) {
|
|
51
|
+
return {
|
|
52
|
+
behavior: 'ask',
|
|
53
|
+
message: `Tool "${tool.name}" requires explicit confirmation.`,
|
|
54
|
+
decisionReason: { type: 'rule', message: `Always-ask rule from ${askRule.source ?? 'settings'}` },
|
|
55
|
+
suggestions: buildSuggestions(tool.name, input),
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
// 2b. Content-specific ask rule
|
|
59
|
+
const contentAsk = matchContentRule(tool.name, input, context.alwaysAskRules, 'ask');
|
|
60
|
+
if (contentAsk) {
|
|
61
|
+
return {
|
|
62
|
+
behavior: 'ask',
|
|
63
|
+
message: contentAsk.message,
|
|
64
|
+
decisionReason: { type: 'contentAsk', message: contentAsk.message },
|
|
65
|
+
suggestions: buildSuggestions(tool.name, input),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
// Continue to tool check
|
|
69
|
+
return checkToolImpl(tool, input, context);
|
|
70
|
+
}
|
|
71
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
72
|
+
// STEP 3: Ask the tool implementation
|
|
73
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
74
|
+
async function checkToolImpl(tool, input, context) {
|
|
75
|
+
// 3a. Run tool.checkPermissions()
|
|
76
|
+
let toolResult;
|
|
77
|
+
try {
|
|
78
|
+
toolResult = tool.checkPermissions
|
|
79
|
+
? await tool.checkPermissions(input, { mode: context.mode })
|
|
80
|
+
: { behavior: 'passthrough', message: '' };
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
toolResult = { behavior: 'ask', message: `Permission check failed for ${tool.name}.` };
|
|
84
|
+
}
|
|
85
|
+
// 3b. Tool denied — stop
|
|
86
|
+
if (toolResult.behavior === 'deny') {
|
|
87
|
+
return {
|
|
88
|
+
...toolResult,
|
|
89
|
+
decisionReason: toolResult.decisionReason ?? { type: 'toolCheck', message: toolResult.message },
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
// 3c. Requires user interaction — even bypass can't skip (but we still ask)
|
|
93
|
+
const requiresInteraction = toolResult.requireExplicitUserApproval === true;
|
|
94
|
+
if (requiresInteraction && toolResult.behavior === 'ask') {
|
|
95
|
+
return {
|
|
96
|
+
...toolResult,
|
|
97
|
+
behavior: 'ask',
|
|
98
|
+
decisionReason: { type: 'requiresInteraction', message: 'This operation requires explicit user approval.' },
|
|
99
|
+
suggestions: suggestionsForTool(tool, input, toolResult),
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
// 3d. Content-specific ask from tool (survives even bypass)
|
|
103
|
+
if (toolResult.behavior === 'ask' && toolResult.decisionReason?.type === 'contentAsk') {
|
|
104
|
+
return {
|
|
105
|
+
...toolResult,
|
|
106
|
+
behavior: 'ask',
|
|
107
|
+
suggestions: suggestionsForTool(tool, input, toolResult),
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// 3e. Safety checks are always ask (even in bypass mode)
|
|
111
|
+
if (toolResult.decisionReason?.type === 'safetyCheck') {
|
|
112
|
+
return {
|
|
113
|
+
...toolResult,
|
|
114
|
+
behavior: 'ask',
|
|
115
|
+
suggestions: suggestionsForTool(tool, input, toolResult),
|
|
116
|
+
};
|
|
117
|
+
}
|
|
118
|
+
return checkModeBypass(tool, input, context, toolResult);
|
|
119
|
+
}
|
|
120
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
121
|
+
// STEP 4: Mode-based bypass
|
|
122
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
123
|
+
async function checkModeBypass(tool, input, context, toolResult) {
|
|
124
|
+
// 4a. bypass mode: everything allowed
|
|
125
|
+
if (context.mode === 'bypass') {
|
|
126
|
+
return { behavior: 'allow', decisionReason: { type: 'mode', message: 'Bypass mode' } };
|
|
127
|
+
}
|
|
128
|
+
// 4b. acceptEdits: auto-allow file edits, prompt for bash
|
|
129
|
+
if (context.mode === 'acceptEdits') {
|
|
130
|
+
const isEdit = ['write', 'create', 'edit', 'modify', 'replace'].includes(tool.name);
|
|
131
|
+
if (isEdit) {
|
|
132
|
+
return { behavior: 'allow', decisionReason: { type: 'mode', message: 'Accept edits mode' } };
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
// 4c. plan mode: read-only only
|
|
136
|
+
if (context.mode === 'plan') {
|
|
137
|
+
if (tool.isReadOnly?.(input)) {
|
|
138
|
+
return { behavior: 'allow', decisionReason: { type: 'mode', message: 'Plan mode (read-only)' } };
|
|
139
|
+
}
|
|
140
|
+
return {
|
|
141
|
+
behavior: 'deny',
|
|
142
|
+
message: `Cannot write/modify in plan mode. Exit plan mode first.`,
|
|
143
|
+
decisionReason: { type: 'mode', message: 'Plan mode blocks writes' },
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// 4d. Entire tool allowed by rule
|
|
147
|
+
const allowRule = context.alwaysAllowRules.find((r) => r.toolName === tool.name && !r.pattern);
|
|
148
|
+
if (allowRule) {
|
|
149
|
+
return { behavior: 'allow', decisionReason: { type: 'rule', message: `Allowed by rule from ${allowRule.source ?? 'settings'}` } };
|
|
150
|
+
}
|
|
151
|
+
// 4e. Content-specific allow rule
|
|
152
|
+
const contentAllow = matchContentRule(tool.name, input, context.alwaysAllowRules, 'allow');
|
|
153
|
+
if (contentAllow) {
|
|
154
|
+
return { behavior: 'allow', decisionReason: { type: 'rule', message: contentAllow.message } };
|
|
155
|
+
}
|
|
156
|
+
// 4f. Tool itself says passthrough (no opinion) → convert to ask in default mode
|
|
157
|
+
if (toolResult.behavior === 'passthrough' || toolResult.behavior === 'allow') {
|
|
158
|
+
const isReadOnly = tool.isReadOnly?.(input) ?? false;
|
|
159
|
+
if (isReadOnly && context.mode === 'default') {
|
|
160
|
+
return { behavior: 'allow', decisionReason: { type: 'mode', message: 'Read-only tool in default mode' } };
|
|
161
|
+
}
|
|
162
|
+
return {
|
|
163
|
+
behavior: 'ask',
|
|
164
|
+
message: toolResult.message || `Allow ${tool.name}?`,
|
|
165
|
+
decisionReason: toolResult.decisionReason ?? { type: 'mode', message: 'Default mode requires confirmation' },
|
|
166
|
+
suggestions: suggestionsForTool(tool, input, toolResult),
|
|
167
|
+
};
|
|
168
|
+
}
|
|
169
|
+
// 4g. Ask the user
|
|
170
|
+
return {
|
|
171
|
+
behavior: 'ask',
|
|
172
|
+
message: toolResult.message || `Allow ${tool.name}?`,
|
|
173
|
+
decisionReason: toolResult.decisionReason,
|
|
174
|
+
suggestions: suggestionsForTool(tool, input, toolResult),
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
178
|
+
// POST-PROCESSING
|
|
179
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
180
|
+
function postProcess(result, _context) {
|
|
181
|
+
return result;
|
|
182
|
+
}
|
|
183
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
184
|
+
// HELPERS
|
|
185
|
+
// ═════════════════════════════════════════════════════════════════════
|
|
186
|
+
function getDenyRuleForTool(toolName, rules) {
|
|
187
|
+
return rules.find((r) => r.toolName === toolName && !r.pattern);
|
|
188
|
+
}
|
|
189
|
+
function matchContentRule(toolName, input, rules, behavior) {
|
|
190
|
+
for (const rule of rules) {
|
|
191
|
+
if (rule.toolName !== toolName || !rule.pattern || rule.behavior !== behavior)
|
|
192
|
+
continue;
|
|
193
|
+
// Check if the pattern appears anywhere in the tool input
|
|
194
|
+
const inputStr = JSON.stringify(input).toLowerCase();
|
|
195
|
+
if (inputStr.includes(rule.pattern.toLowerCase())) {
|
|
196
|
+
return { message: `"${rule.pattern}" matches a ${behavior} rule from ${rule.source ?? 'settings'}.` };
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
function buildSuggestions(toolName, input) {
|
|
202
|
+
const suggestions = [
|
|
203
|
+
{ label: 'Yes', description: 'Allow this operation once', behavior: 'allow' },
|
|
204
|
+
{ label: "Yes, don't ask again for this tool", description: `Always allow ${toolName}`, behavior: 'allowAlways' },
|
|
205
|
+
{ label: 'No', description: 'Deny this operation', behavior: 'deny' },
|
|
206
|
+
];
|
|
207
|
+
return suggestions;
|
|
208
|
+
}
|
|
209
|
+
function suggestionsForTool(tool, input, _toolResult) {
|
|
210
|
+
return buildSuggestions(tool.name, input);
|
|
211
|
+
}
|
|
212
|
+
export function addPermissionRule(rule, context) {
|
|
213
|
+
const updated = { ...context };
|
|
214
|
+
switch (rule.behavior) {
|
|
215
|
+
case 'allow':
|
|
216
|
+
updated.alwaysAllowRules = [...context.alwaysAllowRules, rule];
|
|
217
|
+
break;
|
|
218
|
+
case 'deny':
|
|
219
|
+
updated.alwaysDenyRules = [...context.alwaysDenyRules, rule];
|
|
220
|
+
break;
|
|
221
|
+
case 'ask':
|
|
222
|
+
updated.alwaysAskRules = [...context.alwaysAskRules, rule];
|
|
223
|
+
break;
|
|
224
|
+
}
|
|
225
|
+
return updated;
|
|
226
|
+
}
|
|
227
|
+
export function setPermissionMode(mode, context) {
|
|
228
|
+
if (mode === 'plan' && context.mode !== 'plan') {
|
|
229
|
+
return { ...context, mode, prePlanMode: context.mode };
|
|
230
|
+
}
|
|
231
|
+
if (mode !== 'plan' && context.mode === 'plan') {
|
|
232
|
+
const restored = context.prePlanMode ?? 'default';
|
|
233
|
+
return { ...context, mode, prePlanMode: undefined };
|
|
234
|
+
}
|
|
235
|
+
return { ...context, mode };
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=permissions.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"permissions.js","sourceRoot":"","sources":["../../src/services/permissions.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* sessionStorage.ts — Session persistence for Cray Code.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors Claude Code's pattern: conversations persist as JSONL files
|
|
5
|
+
* in ~/.cray/projects/<sanitized-project-path>/<sessionId>.jsonl.
|
|
6
|
+
*
|
|
7
|
+
* Each line is a JSON object representing one message entry.
|
|
8
|
+
* Messages are chained via parentUuid for conversation reconstruction.
|
|
9
|
+
*/
|
|
10
|
+
import type { Message } from '../types/message.js';
|
|
11
|
+
export declare function sanitizePath(projectPath: string): string;
|
|
12
|
+
export declare function getProjectDir(cwd: string): string;
|
|
13
|
+
export declare function getSessionPath(cwd: string, sessionId: string): string;
|
|
14
|
+
export interface SessionMeta {
|
|
15
|
+
sessionId: string;
|
|
16
|
+
cwd: string;
|
|
17
|
+
firstPrompt: string;
|
|
18
|
+
messageCount: number;
|
|
19
|
+
createdAt: string;
|
|
20
|
+
updatedAt: string;
|
|
21
|
+
}
|
|
22
|
+
export interface SessionListEntry {
|
|
23
|
+
sessionId: string;
|
|
24
|
+
firstPrompt: string;
|
|
25
|
+
messageCount: number;
|
|
26
|
+
createdAt: string;
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* List all saved sessions for the current project directory.
|
|
31
|
+
* Reads the JSONL tail to extract first-prompt metadata.
|
|
32
|
+
*/
|
|
33
|
+
export declare function listSessions(cwd: string): Promise<SessionListEntry[]>;
|
|
34
|
+
/**
|
|
35
|
+
* List sessions across ALL projects (global resume).
|
|
36
|
+
*/
|
|
37
|
+
export declare function listAllSessions(): Promise<(SessionListEntry & {
|
|
38
|
+
cwd: string;
|
|
39
|
+
})[]>;
|
|
40
|
+
export declare function recordTranscriptEntry(cwd: string, sessionId: string, entry: Record<string, unknown>): void;
|
|
41
|
+
export declare function recordMessages(cwd: string, sessionId: string, messages: Message[], parentUuid?: string | null): void;
|
|
42
|
+
/**
|
|
43
|
+
* Flush any pending writes immediately (call before process exit).
|
|
44
|
+
*/
|
|
45
|
+
export declare function flushSessionStorage(): Promise<void>;
|
|
46
|
+
export declare function loadSession(cwd: string, sessionId: string): Promise<Message[]>;
|
|
47
|
+
export declare function loadSessionFromFile(filePath: string): Promise<Message[]>;
|
|
48
|
+
export declare function deleteSession(cwd: string, sessionId: string): Promise<boolean>;
|
|
49
|
+
export declare function getCurrentSessionId(): string | null;
|
|
50
|
+
export declare function setCurrentSessionId(id: string): void;
|
|
51
|
+
//# sourceMappingURL=sessionStorage.d.ts.map
|