gencode-ai 0.1.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/.env.example +11 -0
- package/CLAUDE.md +70 -0
- package/LICENSE +21 -0
- package/README.md +117 -0
- package/dist/agent/agent.d.ts +84 -0
- package/dist/agent/agent.d.ts.map +1 -0
- package/dist/agent/agent.js +233 -0
- package/dist/agent/agent.js.map +1 -0
- package/dist/agent/index.d.ts +6 -0
- package/dist/agent/index.d.ts.map +1 -0
- package/dist/agent/index.js +6 -0
- package/dist/agent/index.js.map +1 -0
- package/dist/agent/types.d.ts +47 -0
- package/dist/agent/types.d.ts.map +1 -0
- package/dist/agent/types.js +5 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/cli/components/App.d.ts +14 -0
- package/dist/cli/components/App.d.ts.map +1 -0
- package/dist/cli/components/App.js +395 -0
- package/dist/cli/components/App.js.map +1 -0
- package/dist/cli/components/CommandSuggestions.d.ts +13 -0
- package/dist/cli/components/CommandSuggestions.d.ts.map +1 -0
- package/dist/cli/components/CommandSuggestions.js +32 -0
- package/dist/cli/components/CommandSuggestions.js.map +1 -0
- package/dist/cli/components/Header.d.ts +9 -0
- package/dist/cli/components/Header.d.ts.map +1 -0
- package/dist/cli/components/Header.js +13 -0
- package/dist/cli/components/Header.js.map +1 -0
- package/dist/cli/components/Input.d.ts +13 -0
- package/dist/cli/components/Input.d.ts.map +1 -0
- package/dist/cli/components/Input.js +27 -0
- package/dist/cli/components/Input.js.map +1 -0
- package/dist/cli/components/Logo.d.ts +2 -0
- package/dist/cli/components/Logo.d.ts.map +1 -0
- package/dist/cli/components/Logo.js +8 -0
- package/dist/cli/components/Logo.js.map +1 -0
- package/dist/cli/components/Messages.d.ts +37 -0
- package/dist/cli/components/Messages.d.ts.map +1 -0
- package/dist/cli/components/Messages.js +106 -0
- package/dist/cli/components/Messages.js.map +1 -0
- package/dist/cli/components/ModelSelector.d.ts +13 -0
- package/dist/cli/components/ModelSelector.d.ts.map +1 -0
- package/dist/cli/components/ModelSelector.js +72 -0
- package/dist/cli/components/ModelSelector.js.map +1 -0
- package/dist/cli/components/Spinner.d.ts +12 -0
- package/dist/cli/components/Spinner.d.ts.map +1 -0
- package/dist/cli/components/Spinner.js +45 -0
- package/dist/cli/components/Spinner.js.map +1 -0
- package/dist/cli/components/index.d.ts +12 -0
- package/dist/cli/components/index.d.ts.map +1 -0
- package/dist/cli/components/index.js +12 -0
- package/dist/cli/components/index.js.map +1 -0
- package/dist/cli/components/theme.d.ts +31 -0
- package/dist/cli/components/theme.d.ts.map +1 -0
- package/dist/cli/components/theme.js +36 -0
- package/dist/cli/components/theme.js.map +1 -0
- package/dist/cli/index-legacy.d.ts +7 -0
- package/dist/cli/index-legacy.d.ts.map +1 -0
- package/dist/cli/index-legacy.js +431 -0
- package/dist/cli/index-legacy.js.map +1 -0
- package/dist/cli/index.d.ts +7 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +116 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/ink-cli.d.ts +7 -0
- package/dist/cli/ink-cli.d.ts.map +1 -0
- package/dist/cli/ink-cli.js +105 -0
- package/dist/cli/ink-cli.js.map +1 -0
- package/dist/cli/session-picker.d.ts +16 -0
- package/dist/cli/session-picker.d.ts.map +1 -0
- package/dist/cli/session-picker.js +280 -0
- package/dist/cli/session-picker.js.map +1 -0
- package/dist/cli/ui.d.ts +61 -0
- package/dist/cli/ui.d.ts.map +1 -0
- package/dist/cli/ui.js +364 -0
- package/dist/cli/ui.js.map +1 -0
- package/dist/config/index.d.ts +7 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +6 -0
- package/dist/config/index.js.map +1 -0
- package/dist/config/manager.d.ts +31 -0
- package/dist/config/manager.d.ts.map +1 -0
- package/dist/config/manager.js +65 -0
- package/dist/config/manager.js.map +1 -0
- package/dist/config/types.d.ts +22 -0
- package/dist/config/types.d.ts.map +1 -0
- package/dist/config/types.js +6 -0
- package/dist/config/types.js.map +1 -0
- package/dist/index.d.ts +12 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +21 -0
- package/dist/index.js.map +1 -0
- package/dist/memory/index.d.ts +10 -0
- package/dist/memory/index.d.ts.map +1 -0
- package/dist/memory/index.js +9 -0
- package/dist/memory/index.js.map +1 -0
- package/dist/memory/init.d.ts +20 -0
- package/dist/memory/init.d.ts.map +1 -0
- package/dist/memory/init.js +332 -0
- package/dist/memory/init.js.map +1 -0
- package/dist/memory/manager.d.ts +85 -0
- package/dist/memory/manager.d.ts.map +1 -0
- package/dist/memory/manager.js +234 -0
- package/dist/memory/manager.js.map +1 -0
- package/dist/memory/types.d.ts +74 -0
- package/dist/memory/types.d.ts.map +1 -0
- package/dist/memory/types.js +6 -0
- package/dist/memory/types.js.map +1 -0
- package/dist/permissions/index.d.ts +7 -0
- package/dist/permissions/index.d.ts.map +1 -0
- package/dist/permissions/index.js +6 -0
- package/dist/permissions/index.js.map +1 -0
- package/dist/permissions/manager.d.ts +32 -0
- package/dist/permissions/manager.d.ts.map +1 -0
- package/dist/permissions/manager.js +79 -0
- package/dist/permissions/manager.js.map +1 -0
- package/dist/permissions/types.d.ts +14 -0
- package/dist/permissions/types.d.ts.map +1 -0
- package/dist/permissions/types.js +17 -0
- package/dist/permissions/types.js.map +1 -0
- package/dist/providers/anthropic.d.ts +20 -0
- package/dist/providers/anthropic.d.ts.map +1 -0
- package/dist/providers/anthropic.js +185 -0
- package/dist/providers/anthropic.js.map +1 -0
- package/dist/providers/gemini.d.ts +21 -0
- package/dist/providers/gemini.d.ts.map +1 -0
- package/dist/providers/gemini.js +241 -0
- package/dist/providers/gemini.js.map +1 -0
- package/dist/providers/index.d.ts +34 -0
- package/dist/providers/index.d.ts.map +1 -0
- package/dist/providers/index.js +72 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/openai.d.ts +19 -0
- package/dist/providers/openai.d.ts.map +1 -0
- package/dist/providers/openai.js +221 -0
- package/dist/providers/openai.js.map +1 -0
- package/dist/providers/types.d.ts +125 -0
- package/dist/providers/types.d.ts.map +1 -0
- package/dist/providers/types.js +6 -0
- package/dist/providers/types.js.map +1 -0
- package/dist/session/index.d.ts +6 -0
- package/dist/session/index.d.ts.map +1 -0
- package/dist/session/index.js +6 -0
- package/dist/session/index.js.map +1 -0
- package/dist/session/manager.d.ts +101 -0
- package/dist/session/manager.d.ts.map +1 -0
- package/dist/session/manager.js +295 -0
- package/dist/session/manager.js.map +1 -0
- package/dist/session/types.d.ts +39 -0
- package/dist/session/types.d.ts.map +1 -0
- package/dist/session/types.js +10 -0
- package/dist/session/types.js.map +1 -0
- package/dist/tools/builtin/bash.d.ts +7 -0
- package/dist/tools/builtin/bash.d.ts.map +1 -0
- package/dist/tools/builtin/bash.js +80 -0
- package/dist/tools/builtin/bash.js.map +1 -0
- package/dist/tools/builtin/edit.d.ts +7 -0
- package/dist/tools/builtin/edit.d.ts.map +1 -0
- package/dist/tools/builtin/edit.js +32 -0
- package/dist/tools/builtin/edit.js.map +1 -0
- package/dist/tools/builtin/glob.d.ts +7 -0
- package/dist/tools/builtin/glob.d.ts.map +1 -0
- package/dist/tools/builtin/glob.js +36 -0
- package/dist/tools/builtin/glob.js.map +1 -0
- package/dist/tools/builtin/grep.d.ts +7 -0
- package/dist/tools/builtin/grep.d.ts.map +1 -0
- package/dist/tools/builtin/grep.js +59 -0
- package/dist/tools/builtin/grep.js.map +1 -0
- package/dist/tools/builtin/read.d.ts +7 -0
- package/dist/tools/builtin/read.d.ts.map +1 -0
- package/dist/tools/builtin/read.js +29 -0
- package/dist/tools/builtin/read.js.map +1 -0
- package/dist/tools/builtin/write.d.ts +7 -0
- package/dist/tools/builtin/write.d.ts.map +1 -0
- package/dist/tools/builtin/write.js +24 -0
- package/dist/tools/builtin/write.js.map +1 -0
- package/dist/tools/index.d.ts +38 -0
- package/dist/tools/index.d.ts.map +1 -0
- package/dist/tools/index.js +32 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/registry.d.ts +22 -0
- package/dist/tools/registry.d.ts.map +1 -0
- package/dist/tools/registry.js +71 -0
- package/dist/tools/registry.js.map +1 -0
- package/dist/tools/types.d.ts +62 -0
- package/dist/tools/types.d.ts.map +1 -0
- package/dist/tools/types.js +126 -0
- package/dist/tools/types.js.map +1 -0
- package/docs/README.md +16 -0
- package/docs/proposals/0001-web-fetch-tool.md +293 -0
- package/docs/proposals/0002-web-search-tool.md +306 -0
- package/docs/proposals/0003-task-subagents.md +333 -0
- package/docs/proposals/0004-plan-mode.md +338 -0
- package/docs/proposals/0005-todo-system.md +299 -0
- package/docs/proposals/0006-memory-system.md +539 -0
- package/docs/proposals/0007-context-management.md +429 -0
- package/docs/proposals/0008-checkpointing.md +327 -0
- package/docs/proposals/0009-hooks-system.md +343 -0
- package/docs/proposals/0010-mcp-integration.md +382 -0
- package/docs/proposals/0011-custom-commands.md +374 -0
- package/docs/proposals/0012-ask-user-question.md +317 -0
- package/docs/proposals/0013-multi-edit-tool.md +345 -0
- package/docs/proposals/0014-lsp-tool.md +478 -0
- package/docs/proposals/0015-ls-tool.md +407 -0
- package/docs/proposals/0016-kill-shell-tool.md +455 -0
- package/docs/proposals/0017-background-tasks.md +489 -0
- package/docs/proposals/0018-parallel-tool-execution.md +415 -0
- package/docs/proposals/0019-session-enhancements.md +462 -0
- package/docs/proposals/0020-session-summarization.md +447 -0
- package/docs/proposals/0021-skills-system.md +409 -0
- package/docs/proposals/0022-plugin-system.md +467 -0
- package/docs/proposals/0023-permission-enhancements.md +470 -0
- package/docs/proposals/0024-keyboard-shortcuts.md +443 -0
- package/docs/proposals/0025-cost-tracking.md +447 -0
- package/docs/proposals/0026-git-integration.md +475 -0
- package/docs/proposals/0027-enhanced-read-tool.md +514 -0
- package/docs/proposals/0028-enhanced-bash-tool.md +511 -0
- package/docs/proposals/0029-notebook-edit-tool.md +413 -0
- package/docs/proposals/0030-plugin-marketplace.md +360 -0
- package/docs/proposals/0031-command-suggestions.md +295 -0
- package/docs/proposals/0032-ide-integrations.md +328 -0
- package/docs/proposals/0033-enterprise-deployment.md +221 -0
- package/docs/proposals/0034-sandboxing.md +273 -0
- package/docs/proposals/0035-auto-updater.md +311 -0
- package/docs/proposals/0036-enhanced-glob-tool.md +267 -0
- package/docs/proposals/0037-enhanced-grep-tool.md +360 -0
- package/docs/proposals/0038-interactive-cli-ui.md +373 -0
- package/docs/proposals/0039-streaming-enhancements.md +359 -0
- package/docs/proposals/0040-multi-provider-enhancements.md +369 -0
- package/docs/proposals/README.md +84 -0
- package/docs/proposals/TEMPLATE.md +57 -0
- package/docs/proposals/research/claude-code-research.md +307 -0
- package/examples/agent-demo.ts +115 -0
- package/examples/basic.ts +166 -0
- package/package.json +50 -0
- package/src/agent/agent.ts +276 -0
- package/src/agent/index.ts +6 -0
- package/src/agent/types.ts +62 -0
- package/src/cli/components/App.tsx +565 -0
- package/src/cli/components/CommandSuggestions.tsx +58 -0
- package/src/cli/components/Header.tsx +36 -0
- package/src/cli/components/Input.tsx +60 -0
- package/src/cli/components/Logo.tsx +16 -0
- package/src/cli/components/Messages.tsx +210 -0
- package/src/cli/components/ModelSelector.tsx +135 -0
- package/src/cli/components/Spinner.tsx +72 -0
- package/src/cli/components/index.ts +21 -0
- package/src/cli/components/theme.ts +36 -0
- package/src/cli/index.tsx +136 -0
- package/src/config/index.ts +7 -0
- package/src/config/manager.ts +77 -0
- package/src/config/types.ts +25 -0
- package/src/index.ts +86 -0
- package/src/permissions/index.ts +7 -0
- package/src/permissions/manager.ts +97 -0
- package/src/permissions/types.ts +29 -0
- package/src/providers/anthropic.ts +224 -0
- package/src/providers/gemini.ts +295 -0
- package/src/providers/index.ts +97 -0
- package/src/providers/openai.ts +261 -0
- package/src/providers/types.ts +181 -0
- package/src/session/index.ts +6 -0
- package/src/session/manager.ts +354 -0
- package/src/session/types.ts +49 -0
- package/src/tools/builtin/bash.ts +92 -0
- package/src/tools/builtin/edit.ts +37 -0
- package/src/tools/builtin/glob.ts +42 -0
- package/src/tools/builtin/grep.ts +67 -0
- package/src/tools/builtin/read.ts +34 -0
- package/src/tools/builtin/write.ts +27 -0
- package/src/tools/index.ts +36 -0
- package/src/tools/registry.ts +83 -0
- package/src/tools/types.ts +172 -0
- package/tsconfig.json +21 -0
|
@@ -0,0 +1,462 @@
|
|
|
1
|
+
# Proposal: Session Enhancements
|
|
2
|
+
|
|
3
|
+
- **Proposal ID**: 0019
|
|
4
|
+
- **Author**: mycode team
|
|
5
|
+
- **Status**: Draft
|
|
6
|
+
- **Created**: 2025-01-15
|
|
7
|
+
- **Updated**: 2025-01-15
|
|
8
|
+
|
|
9
|
+
## Summary
|
|
10
|
+
|
|
11
|
+
Enhance the session management system with advanced features including branching, tagging, search, compression, and improved persistence. This provides users with powerful conversation history management comparable to git workflows.
|
|
12
|
+
|
|
13
|
+
## Motivation
|
|
14
|
+
|
|
15
|
+
The current session system provides basic CRUD operations but lacks:
|
|
16
|
+
|
|
17
|
+
1. **No branching**: Can't explore alternative paths
|
|
18
|
+
2. **Limited search**: Can't find specific conversations
|
|
19
|
+
3. **No compression**: Old sessions waste disk space
|
|
20
|
+
4. **No tagging**: Can't categorize or label sessions
|
|
21
|
+
5. **Basic metadata**: Limited context about session content
|
|
22
|
+
6. **No merge**: Can't combine sessions
|
|
23
|
+
|
|
24
|
+
Enhanced sessions enable sophisticated conversation management.
|
|
25
|
+
|
|
26
|
+
## Claude Code Reference
|
|
27
|
+
|
|
28
|
+
Claude Code provides several session-related features:
|
|
29
|
+
|
|
30
|
+
### Session Resume
|
|
31
|
+
```bash
|
|
32
|
+
claude --resume <session-id>
|
|
33
|
+
claude --continue # Resume most recent
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### Session Commands
|
|
37
|
+
```
|
|
38
|
+
/sessions [--all | -a] # List sessions
|
|
39
|
+
/resume [index|id] # Resume session
|
|
40
|
+
/new [title] # New session
|
|
41
|
+
/fork [title] # Fork current
|
|
42
|
+
/clear # Clear history
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Key Features
|
|
46
|
+
- Project-scoped sessions (by working directory)
|
|
47
|
+
- Automatic summarization for long conversations
|
|
48
|
+
- Fork capability for exploration
|
|
49
|
+
- Session persistence across restarts
|
|
50
|
+
|
|
51
|
+
## Detailed Design
|
|
52
|
+
|
|
53
|
+
### Enhanced Session Types
|
|
54
|
+
|
|
55
|
+
```typescript
|
|
56
|
+
// src/session/types.ts
|
|
57
|
+
interface Session {
|
|
58
|
+
metadata: SessionMetadata;
|
|
59
|
+
messages: Message[];
|
|
60
|
+
branches?: Branch[];
|
|
61
|
+
tags?: string[];
|
|
62
|
+
summary?: SessionSummary;
|
|
63
|
+
compressed?: boolean;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
interface SessionMetadata {
|
|
67
|
+
id: string;
|
|
68
|
+
title: string;
|
|
69
|
+
createdAt: string;
|
|
70
|
+
updatedAt: string;
|
|
71
|
+
provider: string;
|
|
72
|
+
model: string;
|
|
73
|
+
cwd: string;
|
|
74
|
+
messageCount: number;
|
|
75
|
+
tokenUsage?: TokenUsage;
|
|
76
|
+
parentId?: string; // For forked sessions
|
|
77
|
+
branchPoint?: number; // Message index where branched
|
|
78
|
+
description?: string; // User-provided description
|
|
79
|
+
archived?: boolean; // Archived sessions
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface TokenUsage {
|
|
83
|
+
input: number;
|
|
84
|
+
output: number;
|
|
85
|
+
total: number;
|
|
86
|
+
estimatedCost?: number;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
interface Branch {
|
|
90
|
+
id: string;
|
|
91
|
+
name: string;
|
|
92
|
+
messageIndex: number; // Where branch diverges
|
|
93
|
+
sessionId: string; // Reference to branch session
|
|
94
|
+
createdAt: string;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
interface SessionSummary {
|
|
98
|
+
topics: string[];
|
|
99
|
+
keyActions: string[];
|
|
100
|
+
filesModified: string[];
|
|
101
|
+
generatedAt: string;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
interface SessionSearchResult {
|
|
105
|
+
session: SessionMetadata;
|
|
106
|
+
matches: SearchMatch[];
|
|
107
|
+
score: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
interface SearchMatch {
|
|
111
|
+
messageIndex: number;
|
|
112
|
+
role: 'user' | 'assistant';
|
|
113
|
+
snippet: string;
|
|
114
|
+
highlight: [number, number][];
|
|
115
|
+
}
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Enhanced Session Manager
|
|
119
|
+
|
|
120
|
+
```typescript
|
|
121
|
+
// src/session/manager.ts
|
|
122
|
+
class SessionManager {
|
|
123
|
+
// Existing methods...
|
|
124
|
+
|
|
125
|
+
// === New: Branching ===
|
|
126
|
+
async branch(
|
|
127
|
+
sessionId: string,
|
|
128
|
+
messageIndex: number,
|
|
129
|
+
branchName?: string
|
|
130
|
+
): Promise<Session> {
|
|
131
|
+
const session = await this.load(sessionId);
|
|
132
|
+
if (!session) throw new Error('Session not found');
|
|
133
|
+
|
|
134
|
+
// Create new session with messages up to branch point
|
|
135
|
+
const branchSession = await this.create({
|
|
136
|
+
provider: session.metadata.provider,
|
|
137
|
+
model: session.metadata.model,
|
|
138
|
+
cwd: session.metadata.cwd,
|
|
139
|
+
title: branchName || `Branch of ${session.metadata.title}`,
|
|
140
|
+
parentId: sessionId
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
// Copy messages up to branch point
|
|
144
|
+
branchSession.messages = session.messages.slice(0, messageIndex + 1);
|
|
145
|
+
branchSession.metadata.branchPoint = messageIndex;
|
|
146
|
+
|
|
147
|
+
// Record branch in parent
|
|
148
|
+
session.branches = session.branches || [];
|
|
149
|
+
session.branches.push({
|
|
150
|
+
id: generateId(),
|
|
151
|
+
name: branchName || `branch-${session.branches.length + 1}`,
|
|
152
|
+
messageIndex,
|
|
153
|
+
sessionId: branchSession.metadata.id,
|
|
154
|
+
createdAt: new Date().toISOString()
|
|
155
|
+
});
|
|
156
|
+
|
|
157
|
+
await this.save(session);
|
|
158
|
+
await this.save(branchSession);
|
|
159
|
+
|
|
160
|
+
return branchSession;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
async listBranches(sessionId: string): Promise<Branch[]> {
|
|
164
|
+
const session = await this.load(sessionId);
|
|
165
|
+
return session?.branches || [];
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// === New: Tagging ===
|
|
169
|
+
async addTag(sessionId: string, tag: string): Promise<void> {
|
|
170
|
+
const session = await this.load(sessionId);
|
|
171
|
+
if (!session) throw new Error('Session not found');
|
|
172
|
+
|
|
173
|
+
session.tags = session.tags || [];
|
|
174
|
+
if (!session.tags.includes(tag)) {
|
|
175
|
+
session.tags.push(tag);
|
|
176
|
+
await this.save(session);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async removeTag(sessionId: string, tag: string): Promise<void> {
|
|
181
|
+
const session = await this.load(sessionId);
|
|
182
|
+
if (!session) throw new Error('Session not found');
|
|
183
|
+
|
|
184
|
+
session.tags = (session.tags || []).filter(t => t !== tag);
|
|
185
|
+
await this.save(session);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
async findByTag(tag: string): Promise<SessionMetadata[]> {
|
|
189
|
+
const all = await this.listAll();
|
|
190
|
+
return all.filter(s => s.tags?.includes(tag));
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
// === New: Search ===
|
|
194
|
+
async search(
|
|
195
|
+
query: string,
|
|
196
|
+
options?: { cwd?: string; limit?: number }
|
|
197
|
+
): Promise<SessionSearchResult[]> {
|
|
198
|
+
const sessions = options?.cwd
|
|
199
|
+
? await this.list({ cwd: options.cwd })
|
|
200
|
+
: await this.listAll();
|
|
201
|
+
|
|
202
|
+
const results: SessionSearchResult[] = [];
|
|
203
|
+
const queryLower = query.toLowerCase();
|
|
204
|
+
|
|
205
|
+
for (const metadata of sessions) {
|
|
206
|
+
const session = await this.load(metadata.id);
|
|
207
|
+
if (!session) continue;
|
|
208
|
+
|
|
209
|
+
const matches: SearchMatch[] = [];
|
|
210
|
+
|
|
211
|
+
session.messages.forEach((msg, idx) => {
|
|
212
|
+
const content = typeof msg.content === 'string'
|
|
213
|
+
? msg.content
|
|
214
|
+
: JSON.stringify(msg.content);
|
|
215
|
+
|
|
216
|
+
const contentLower = content.toLowerCase();
|
|
217
|
+
const matchIndex = contentLower.indexOf(queryLower);
|
|
218
|
+
|
|
219
|
+
if (matchIndex !== -1) {
|
|
220
|
+
const start = Math.max(0, matchIndex - 50);
|
|
221
|
+
const end = Math.min(content.length, matchIndex + query.length + 50);
|
|
222
|
+
matches.push({
|
|
223
|
+
messageIndex: idx,
|
|
224
|
+
role: msg.role as 'user' | 'assistant',
|
|
225
|
+
snippet: content.slice(start, end),
|
|
226
|
+
highlight: [[matchIndex - start, matchIndex - start + query.length]]
|
|
227
|
+
});
|
|
228
|
+
}
|
|
229
|
+
});
|
|
230
|
+
|
|
231
|
+
if (matches.length > 0) {
|
|
232
|
+
results.push({
|
|
233
|
+
session: metadata,
|
|
234
|
+
matches,
|
|
235
|
+
score: matches.length
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Sort by relevance
|
|
241
|
+
results.sort((a, b) => b.score - a.score);
|
|
242
|
+
|
|
243
|
+
return options?.limit ? results.slice(0, options.limit) : results;
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
// === New: Compression ===
|
|
247
|
+
async compress(sessionId: string): Promise<void> {
|
|
248
|
+
const session = await this.load(sessionId);
|
|
249
|
+
if (!session) throw new Error('Session not found');
|
|
250
|
+
|
|
251
|
+
// Generate summary before compression
|
|
252
|
+
session.summary = await this.generateSummary(session);
|
|
253
|
+
|
|
254
|
+
// Compress messages (keep first and last N)
|
|
255
|
+
const KEEP_RECENT = 10;
|
|
256
|
+
if (session.messages.length > KEEP_RECENT * 2) {
|
|
257
|
+
const first = session.messages.slice(0, 5);
|
|
258
|
+
const last = session.messages.slice(-KEEP_RECENT);
|
|
259
|
+
session.messages = [
|
|
260
|
+
...first,
|
|
261
|
+
{
|
|
262
|
+
role: 'system',
|
|
263
|
+
content: `[${session.messages.length - first.length - last.length} messages compressed]`
|
|
264
|
+
},
|
|
265
|
+
...last
|
|
266
|
+
];
|
|
267
|
+
session.compressed = true;
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
await this.save(session);
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async archive(sessionId: string): Promise<void> {
|
|
274
|
+
const session = await this.load(sessionId);
|
|
275
|
+
if (!session) throw new Error('Session not found');
|
|
276
|
+
|
|
277
|
+
session.metadata.archived = true;
|
|
278
|
+
await this.compress(sessionId);
|
|
279
|
+
await this.save(session);
|
|
280
|
+
|
|
281
|
+
// Move to archive directory
|
|
282
|
+
const archivePath = path.join(this.archiveDir, `${sessionId}.json.gz`);
|
|
283
|
+
await this.compressAndMove(session, archivePath);
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
private async generateSummary(session: Session): Promise<SessionSummary> {
|
|
287
|
+
// Extract topics from messages
|
|
288
|
+
const topics: Set<string> = new Set();
|
|
289
|
+
const actions: string[] = [];
|
|
290
|
+
const files: Set<string> = new Set();
|
|
291
|
+
|
|
292
|
+
for (const msg of session.messages) {
|
|
293
|
+
// Extract file paths mentioned
|
|
294
|
+
const filePaths = extractFilePaths(msg.content);
|
|
295
|
+
filePaths.forEach(f => files.add(f));
|
|
296
|
+
|
|
297
|
+
// Extract tool actions
|
|
298
|
+
if (msg.role === 'assistant' && typeof msg.content !== 'string') {
|
|
299
|
+
for (const block of msg.content) {
|
|
300
|
+
if (block.type === 'tool_use') {
|
|
301
|
+
actions.push(`${block.name}: ${summarizeInput(block.input)}`);
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
return {
|
|
308
|
+
topics: Array.from(topics),
|
|
309
|
+
keyActions: actions.slice(0, 10),
|
|
310
|
+
filesModified: Array.from(files),
|
|
311
|
+
generatedAt: new Date().toISOString()
|
|
312
|
+
};
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### New CLI Commands
|
|
318
|
+
|
|
319
|
+
```typescript
|
|
320
|
+
// Additional CLI commands
|
|
321
|
+
const sessionCommands = {
|
|
322
|
+
'/branch': 'Create a branch at current or specified message',
|
|
323
|
+
'/tag': 'Add or remove tags from current session',
|
|
324
|
+
'/search': 'Search across all sessions',
|
|
325
|
+
'/archive': 'Archive and compress old sessions',
|
|
326
|
+
'/branches': 'List all branches of current session',
|
|
327
|
+
'/describe': 'Add description to current session'
|
|
328
|
+
};
|
|
329
|
+
|
|
330
|
+
// Examples:
|
|
331
|
+
// /branch "experiment-1"
|
|
332
|
+
// /branch 5 "try-different-approach"
|
|
333
|
+
// /tag add important
|
|
334
|
+
// /tag remove wip
|
|
335
|
+
// /search "authentication error"
|
|
336
|
+
// /archive
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### File Changes
|
|
340
|
+
|
|
341
|
+
| File | Action | Description |
|
|
342
|
+
|------|--------|-------------|
|
|
343
|
+
| `src/session/types.ts` | Modify | Add new types |
|
|
344
|
+
| `src/session/manager.ts` | Modify | Add new methods |
|
|
345
|
+
| `src/session/search.ts` | Create | Search implementation |
|
|
346
|
+
| `src/session/compression.ts` | Create | Compression utilities |
|
|
347
|
+
| `src/cli/commands/session.ts` | Modify | Add new commands |
|
|
348
|
+
|
|
349
|
+
## User Experience
|
|
350
|
+
|
|
351
|
+
### Branching
|
|
352
|
+
```
|
|
353
|
+
User: /branch "try-redis-cache"
|
|
354
|
+
|
|
355
|
+
Created branch 'try-redis-cache' at message 15.
|
|
356
|
+
Now working on branch. Original session preserved.
|
|
357
|
+
|
|
358
|
+
Switch back with: /resume original-session-id
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
### Tagging
|
|
362
|
+
```
|
|
363
|
+
User: /tag add important
|
|
364
|
+
Added tag 'important' to current session.
|
|
365
|
+
|
|
366
|
+
User: /sessions --tag important
|
|
367
|
+
Sessions tagged 'important':
|
|
368
|
+
1. [abc123] Fix authentication bug (2 hours ago)
|
|
369
|
+
2. [def456] Implement caching layer (yesterday)
|
|
370
|
+
```
|
|
371
|
+
|
|
372
|
+
### Search
|
|
373
|
+
```
|
|
374
|
+
User: /search "database migration"
|
|
375
|
+
|
|
376
|
+
Found 3 matches:
|
|
377
|
+
|
|
378
|
+
1. [abc123] Database refactoring (2 days ago)
|
|
379
|
+
Message 12: "...let me write the database migration script..."
|
|
380
|
+
|
|
381
|
+
2. [def456] Schema update (1 week ago)
|
|
382
|
+
Message 5: "...running database migration for users table..."
|
|
383
|
+
|
|
384
|
+
3. [ghi789] Production fix (2 weeks ago)
|
|
385
|
+
Message 23: "...database migration failed, rolling back..."
|
|
386
|
+
```
|
|
387
|
+
|
|
388
|
+
### Archive
|
|
389
|
+
```
|
|
390
|
+
User: /archive
|
|
391
|
+
|
|
392
|
+
Archived session: abc123
|
|
393
|
+
- Generated summary
|
|
394
|
+
- Compressed 156 messages → 15 messages
|
|
395
|
+
- Saved 2.3 MB
|
|
396
|
+
|
|
397
|
+
Archived sessions available in ~/.mycode/sessions/archive/
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Alternatives Considered
|
|
401
|
+
|
|
402
|
+
### Alternative 1: Git-based Storage
|
|
403
|
+
Store sessions in git repository.
|
|
404
|
+
|
|
405
|
+
**Pros**: Built-in branching, versioning
|
|
406
|
+
**Cons**: Heavy, complex for simple use
|
|
407
|
+
**Decision**: Deferred - Consider for enterprise
|
|
408
|
+
|
|
409
|
+
### Alternative 2: SQLite Backend
|
|
410
|
+
Use SQLite instead of JSON files.
|
|
411
|
+
|
|
412
|
+
**Pros**: Better search, indexing
|
|
413
|
+
**Cons**: Added dependency, complexity
|
|
414
|
+
**Decision**: Deferred - Phase 2 enhancement
|
|
415
|
+
|
|
416
|
+
### Alternative 3: Cloud Sync
|
|
417
|
+
Sync sessions across devices.
|
|
418
|
+
|
|
419
|
+
**Pros**: Mobility, backup
|
|
420
|
+
**Cons**: Privacy concerns, complexity
|
|
421
|
+
**Decision**: Deferred - Future feature
|
|
422
|
+
|
|
423
|
+
## Security Considerations
|
|
424
|
+
|
|
425
|
+
1. **Sensitive Data**: Search may expose secrets in old sessions
|
|
426
|
+
2. **Compression Safety**: Ensure compressed data is recoverable
|
|
427
|
+
3. **Archive Encryption**: Consider encrypting archived sessions
|
|
428
|
+
4. **Access Control**: Prevent cross-user session access
|
|
429
|
+
5. **Cleanup**: Properly delete archived sessions on request
|
|
430
|
+
|
|
431
|
+
## Testing Strategy
|
|
432
|
+
|
|
433
|
+
1. **Unit Tests**:
|
|
434
|
+
- Branching logic
|
|
435
|
+
- Search matching
|
|
436
|
+
- Compression/decompression
|
|
437
|
+
- Tag operations
|
|
438
|
+
|
|
439
|
+
2. **Integration Tests**:
|
|
440
|
+
- Full branch workflow
|
|
441
|
+
- Search across many sessions
|
|
442
|
+
- Archive and restore
|
|
443
|
+
|
|
444
|
+
3. **Manual Testing**:
|
|
445
|
+
- Large session handling
|
|
446
|
+
- Edge cases in search
|
|
447
|
+
|
|
448
|
+
## Migration Path
|
|
449
|
+
|
|
450
|
+
1. **Phase 1**: Tagging and search
|
|
451
|
+
2. **Phase 2**: Branching support
|
|
452
|
+
3. **Phase 3**: Compression and archival
|
|
453
|
+
4. **Phase 4**: Summary generation
|
|
454
|
+
5. **Phase 5**: Export/import improvements
|
|
455
|
+
|
|
456
|
+
Backward compatible - existing sessions work unchanged.
|
|
457
|
+
|
|
458
|
+
## References
|
|
459
|
+
|
|
460
|
+
- [Existing Session Implementation](../../../src/session/manager.ts)
|
|
461
|
+
- [Claude Code Session Commands](https://code.claude.com/docs/en/cli)
|
|
462
|
+
- [Git Branching Model](https://git-scm.com/book/en/v2/Git-Branching-Branches-in-a-Nutshell)
|