@allternit/gizzi-code 1.0.0 → 1.0.1
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/bin/gizzi +4 -0
- package/bin/gizzi-ink +5 -0
- package/package.json +137 -31
- package/src/Tool.ts +26 -0
- package/src/bootstrap/state.ts +165 -322
- package/src/commands.ts +209 -0
- package/src/context/QueuedMessageContext.tsx +63 -0
- package/src/context/fpsMetrics.tsx +30 -0
- package/src/context/mailbox.tsx +38 -0
- package/src/context/modalContext.tsx +58 -0
- package/src/context/notifications.tsx +240 -0
- package/src/context/overlayContext.tsx +151 -0
- package/src/context/promptOverlayContext.tsx +125 -0
- package/src/context/stats.tsx +220 -0
- package/src/context/voice.tsx +88 -0
- package/src/hooks/useCanUseTool.ts +11 -0
- package/src/hooks/useExitOnCtrlCD.ts +40 -187
- package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +68 -0
- package/src/hooks/useKeybinding.ts +68 -209
- package/src/hooks/useTerminalSize.ts +31 -99
- package/src/hooks.ts +37 -0
- package/src/ink.ts +204 -0
- package/src/main.ts +7 -0
- package/src/types/command.ts +216 -0
- package/src/types/connectorText.ts +39 -0
- package/src/types/fileSuggestion.ts +15 -0
- package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
- package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
- package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
- package/src/types/generated/google/protobuf/timestamp.ts +187 -0
- package/src/types/hooks.ts +319 -0
- package/src/types/ids.ts +44 -0
- package/src/types/logs.ts +331 -0
- package/src/types/merged/index.ts +5 -0
- package/src/types/merged/message.ts +552 -0
- package/src/types/message.ts +927 -186
- package/src/types/messageQueueTypes.ts +21 -0
- package/src/types/notebook.ts +72 -0
- package/src/types/permissions.ts +447 -0
- package/src/types/plugin.ts +363 -0
- package/src/types/statusLine.ts +15 -0
- package/src/types/textInputTypes.ts +387 -0
- package/src/types/tools.ts +149 -0
- package/src/types/utils.ts +20 -0
- package/src/utils/advisor.ts +12 -0
- package/src/utils/api.ts +29 -0
- package/src/utils/array.ts +7 -0
- package/src/utils/attachments.ts +60 -0
- package/src/utils/auth.ts +3 -0
- package/src/utils/claudeInChrome/chromeNativeHost.ts +15 -0
- package/src/utils/claudeInChrome/common.ts +12 -0
- package/src/utils/claudeInChrome/mcpServer.ts +15 -0
- package/src/utils/computerUse/common.ts +19 -0
- package/src/utils/computerUse/mcpServer.ts +15 -0
- package/src/utils/config.ts +35 -0
- package/src/utils/context.ts +19 -0
- package/src/utils/cwd.ts +3 -0
- package/src/utils/debug.ts +3 -0
- package/src/utils/earlyInput.ts +7 -0
- package/src/utils/effort.ts +13 -0
- package/src/utils/embeddedTools.ts +12 -0
- package/src/utils/envUtils.ts +3 -0
- package/src/utils/errors.ts +3 -0
- package/src/utils/execFileNoThrow.ts +24 -0
- package/src/utils/feature-flags.ts +112 -0
- package/src/utils/file.ts +3 -0
- package/src/utils/fileHistory.ts +17 -0
- package/src/utils/fingerprint.ts +7 -0
- package/src/utils/format.ts +75 -305
- package/src/utils/frontmatterParser.ts +33 -0
- package/src/utils/fsOperations.ts +31 -0
- package/src/utils/fullscreen.ts +40 -350
- package/src/utils/git.ts +15 -0
- package/src/utils/imageResizer.ts +30 -0
- package/src/utils/lazySchema.ts +9 -0
- package/src/utils/log.ts +3 -0
- package/src/utils/markdownConfigLoader.ts +12 -0
- package/src/utils/messages.ts +13 -0
- package/src/utils/migration.ts +137 -0
- package/src/utils/model/providers.ts +15 -0
- package/src/utils/path.ts +3 -0
- package/src/utils/permissions/PermissionResult.ts +14 -0
- package/src/utils/permissions/autoModeState.ts +12 -0
- package/src/utils/permissions/filesystem.ts +12 -0
- package/src/utils/plugins/loadPluginOutputStyles.ts +12 -0
- package/src/utils/plugins/schemas.ts +25 -0
- package/src/utils/process.ts +16 -0
- package/src/utils/sandbox/sandbox-adapter.ts +19 -0
- package/src/utils/sessionStorage.ts +238 -472
- package/src/utils/settings/constants.ts +10 -0
- package/src/utils/settings/settings.ts +19 -0
- package/src/utils/settings/types.ts +18 -0
- package/src/utils/shell/shellToolUtils.ts +9 -0
- package/src/utils/sinks.ts +11 -0
- package/src/utils/sleep.ts +7 -0
- package/src/utils/sliceAnsi.ts +7 -0
- package/src/utils/slowOperations.ts +3 -0
- package/src/utils/startupProfiler.ts +11 -0
- package/src/utils/stringUtils.ts +106 -0
- package/src/utils/systemPromptType.ts +9 -0
- package/src/utils/teleport/api.ts +15 -0
- package/src/utils/textHighlighting.ts +16 -0
- package/src/utils/theme.ts +17 -0
- package/src/utils/thinking.ts +58 -0
- package/src/utils/tokens.ts +11 -0
- package/src/utils/toolResultStorage.ts +17 -0
- package/src/utils/worktreeModeEnabled.ts +7 -0
- package/WORKSPACE_INTEGRATION.md +0 -290
- package/chat-sessions/sessions-index.json +0 -98
- package/package.json.original +0 -31
- package/package.json.publish +0 -47
- package/src/bootstrap/state.d.ts +0 -169
- package/src/bootstrap/state.js +0 -261
- package/src/context/pack-builder.d.ts +0 -24
- package/src/context/pack-builder.js +0 -281
- package/src/hooks/useExitOnCtrlCD.d.ts +0 -86
- package/src/hooks/useExitOnCtrlCD.js +0 -130
- package/src/hooks/useKeybinding.d.ts +0 -89
- package/src/hooks/useKeybinding.js +0 -163
- package/src/hooks/useTerminalSize.d.ts +0 -41
- package/src/hooks/useTerminalSize.js +0 -90
- package/src/index.d.ts +0 -23
- package/src/index.js +0 -24
- package/src/runtime/brand/brand.d.ts +0 -488
- package/src/runtime/brand/brand.js +0 -464
- package/src/runtime/brand/brand.ts +0 -667
- package/src/runtime/services/tokenEstimation.d.ts +0 -187
- package/src/runtime/services/tokenEstimation.js +0 -423
- package/src/runtime/services/tokenEstimation.ts +0 -547
- package/src/runtime/tools/Tool.d.ts +0 -239
- package/src/runtime/tools/Tool.js +0 -285
- package/src/runtime/tools/Tool.ts +0 -524
- package/src/scheduler/TaskScheduler.d.ts +0 -98
- package/src/scheduler/TaskScheduler.js +0 -201
- package/src/scheduler/TaskScheduler.ts +0 -259
- package/src/state/AppStateStore.d.ts +0 -347
- package/src/state/AppStateStore.js +0 -439
- package/src/state/AppStateStore.ts +0 -658
- package/src/state/WorkspaceStateStore.d.ts +0 -43
- package/src/state/WorkspaceStateStore.js +0 -224
- package/src/state/WorkspaceStateStore.ts +0 -297
- package/src/types/message.d.ts +0 -190
- package/src/types/message.js +0 -77
- package/src/utils/format.d.ts +0 -126
- package/src/utils/format.js +0 -230
- package/src/utils/fullscreen.d.ts +0 -161
- package/src/utils/fullscreen.js +0 -277
- package/src/utils/sessionStorage.d.ts +0 -210
- package/src/utils/sessionStorage.js +0 -435
- package/src/watcher/WorkspaceWatcher.d.ts +0 -70
- package/src/watcher/WorkspaceWatcher.js +0 -191
- package/src/watcher/WorkspaceWatcher.ts +0 -251
- package/src/workspace/loader.d.ts +0 -30
- package/src/workspace/loader.js +0 -117
- package/src/workspace/types.d.ts +0 -91
- package/src/workspace/types.js +0 -7
- package/threads/thread_1775361175022.json +0 -9
- package/tsconfig.json +0 -14
|
@@ -1,435 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Session storage utilities for gizzi-code integration
|
|
3
|
-
* @module utils/sessionStorage
|
|
4
|
-
*
|
|
5
|
-
* Provides session persistence, storage management, and user type detection
|
|
6
|
-
* with safe fallbacks for environments without storage access.
|
|
7
|
-
*/
|
|
8
|
-
/**
|
|
9
|
-
* Storage keys used throughout the application
|
|
10
|
-
* @constant {Record<string, string>}
|
|
11
|
-
*/
|
|
12
|
-
export const STORAGE_KEYS = {
|
|
13
|
-
SESSION: 'gizzi_session',
|
|
14
|
-
USER_TYPE: 'gizzi_user_type',
|
|
15
|
-
MESSAGES: 'gizzi_messages',
|
|
16
|
-
PREFERENCES: 'gizzi_preferences',
|
|
17
|
-
LAST_ACTIVITY: 'gizzi_last_activity',
|
|
18
|
-
SESSION_METADATA: 'gizzi_session_metadata',
|
|
19
|
-
};
|
|
20
|
-
/**
|
|
21
|
-
* Valid user types for runtime validation
|
|
22
|
-
* @constant {readonly UserType[]}
|
|
23
|
-
*/
|
|
24
|
-
export const VALID_USER_TYPES = [
|
|
25
|
-
'anonymous',
|
|
26
|
-
'free',
|
|
27
|
-
'pro',
|
|
28
|
-
'enterprise',
|
|
29
|
-
'admin',
|
|
30
|
-
];
|
|
31
|
-
/**
|
|
32
|
-
* Checks if localStorage/sessionStorage is available
|
|
33
|
-
* @returns {boolean} True if storage APIs are available
|
|
34
|
-
*/
|
|
35
|
-
function isStorageAvailable() {
|
|
36
|
-
try {
|
|
37
|
-
if (typeof window === 'undefined') {
|
|
38
|
-
return false;
|
|
39
|
-
}
|
|
40
|
-
const testKey = '__gizzi_storage_test__';
|
|
41
|
-
window.sessionStorage.setItem(testKey, 'test');
|
|
42
|
-
window.sessionStorage.removeItem(testKey);
|
|
43
|
-
return true;
|
|
44
|
-
}
|
|
45
|
-
catch {
|
|
46
|
-
return false;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Safely parses JSON with error handling
|
|
51
|
-
*
|
|
52
|
-
* @template T
|
|
53
|
-
* @param {string} json - JSON string to parse
|
|
54
|
-
* @param {T} [defaultValue] - Default value if parsing fails
|
|
55
|
-
* @returns {T | null} Parsed value or default/null on error
|
|
56
|
-
*/
|
|
57
|
-
function safeJsonParse(json, defaultValue) {
|
|
58
|
-
try {
|
|
59
|
-
return JSON.parse(json);
|
|
60
|
-
}
|
|
61
|
-
catch {
|
|
62
|
-
return defaultValue ?? null;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Safely stringifies JSON with error handling
|
|
67
|
-
*
|
|
68
|
-
* @param {unknown} value - Value to stringify
|
|
69
|
-
* @returns {string | null} JSON string or null on error
|
|
70
|
-
*/
|
|
71
|
-
function safeJsonStringify(value) {
|
|
72
|
-
try {
|
|
73
|
-
return JSON.stringify(value);
|
|
74
|
-
}
|
|
75
|
-
catch {
|
|
76
|
-
return null;
|
|
77
|
-
}
|
|
78
|
-
}
|
|
79
|
-
/**
|
|
80
|
-
* In-memory fallback storage when sessionStorage is unavailable
|
|
81
|
-
* @constant {Map<string, string>}
|
|
82
|
-
*/
|
|
83
|
-
const memoryStorage = new Map();
|
|
84
|
-
/**
|
|
85
|
-
* Gets an item from storage (sessionStorage or memory fallback)
|
|
86
|
-
*
|
|
87
|
-
* @param {string} key - Storage key
|
|
88
|
-
* @returns {string | null} The stored value or null
|
|
89
|
-
*/
|
|
90
|
-
function getStorageItem(key) {
|
|
91
|
-
if (isStorageAvailable()) {
|
|
92
|
-
return window.sessionStorage.getItem(key);
|
|
93
|
-
}
|
|
94
|
-
return memoryStorage.get(key) ?? null;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* Sets an item in storage (sessionStorage or memory fallback)
|
|
98
|
-
*
|
|
99
|
-
* @param {string} key - Storage key
|
|
100
|
-
* @param {string} value - Value to store
|
|
101
|
-
* @returns {boolean} True if successful
|
|
102
|
-
*/
|
|
103
|
-
function setStorageItem(key, value) {
|
|
104
|
-
try {
|
|
105
|
-
if (isStorageAvailable()) {
|
|
106
|
-
window.sessionStorage.setItem(key, value);
|
|
107
|
-
}
|
|
108
|
-
else {
|
|
109
|
-
memoryStorage.set(key, value);
|
|
110
|
-
}
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
catch (error) {
|
|
114
|
-
console.error(`Failed to set storage item '${key}':`, error);
|
|
115
|
-
return false;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
/**
|
|
119
|
-
* Removes an item from storage
|
|
120
|
-
*
|
|
121
|
-
* @param {string} key - Storage key to remove
|
|
122
|
-
* @returns {boolean} True if successful
|
|
123
|
-
*/
|
|
124
|
-
function removeStorageItem(key) {
|
|
125
|
-
try {
|
|
126
|
-
if (isStorageAvailable()) {
|
|
127
|
-
window.sessionStorage.removeItem(key);
|
|
128
|
-
}
|
|
129
|
-
else {
|
|
130
|
-
memoryStorage.delete(key);
|
|
131
|
-
}
|
|
132
|
-
return true;
|
|
133
|
-
}
|
|
134
|
-
catch (error) {
|
|
135
|
-
console.error(`Failed to remove storage item '${key}':`, error);
|
|
136
|
-
return false;
|
|
137
|
-
}
|
|
138
|
-
}
|
|
139
|
-
/**
|
|
140
|
-
* Saves the current session to storage
|
|
141
|
-
*
|
|
142
|
-
* @param {UserSession} session - The session to save
|
|
143
|
-
* @param {Object} [options] - Save options
|
|
144
|
-
* @param {TypedMessage[]} [options.messages] - Messages to persist
|
|
145
|
-
* @param {Record<string, unknown>} [options.preferences] - Preferences to persist
|
|
146
|
-
* @returns {StorageResult<void>} Result of the save operation
|
|
147
|
-
* @example
|
|
148
|
-
* ```typescript
|
|
149
|
-
* const result = saveSession(session, { messages, preferences });
|
|
150
|
-
* if (!result.success) {
|
|
151
|
-
* console.error('Failed to save session:', result.error);
|
|
152
|
-
* }
|
|
153
|
-
* ```
|
|
154
|
-
*/
|
|
155
|
-
export function saveSession(session, options = {}) {
|
|
156
|
-
if (!session) {
|
|
157
|
-
return { success: false, data: null, error: 'Session is required' };
|
|
158
|
-
}
|
|
159
|
-
const existingMetadata = loadSessionMetadata();
|
|
160
|
-
const metadata = {
|
|
161
|
-
createdAt: existingMetadata?.createdAt ?? new Date().toISOString(),
|
|
162
|
-
lastActivity: new Date().toISOString(),
|
|
163
|
-
messageCount: options.messages?.length ?? 0,
|
|
164
|
-
version: 1,
|
|
165
|
-
deviceInfo: isStorageAvailable()
|
|
166
|
-
? {
|
|
167
|
-
userAgent: navigator.userAgent,
|
|
168
|
-
platform: navigator.platform,
|
|
169
|
-
language: navigator.language,
|
|
170
|
-
}
|
|
171
|
-
: undefined,
|
|
172
|
-
};
|
|
173
|
-
const sessionData = {
|
|
174
|
-
session,
|
|
175
|
-
metadata,
|
|
176
|
-
messages: options.messages ?? [],
|
|
177
|
-
preferences: options.preferences ?? {},
|
|
178
|
-
};
|
|
179
|
-
const serialized = safeJsonStringify(sessionData);
|
|
180
|
-
if (!serialized) {
|
|
181
|
-
return { success: false, data: null, error: 'Failed to serialize session data' };
|
|
182
|
-
}
|
|
183
|
-
if (!setStorageItem(STORAGE_KEYS.SESSION, serialized)) {
|
|
184
|
-
return { success: false, data: null, error: 'Failed to write to storage' };
|
|
185
|
-
}
|
|
186
|
-
// Also save user type separately for quick access
|
|
187
|
-
setStorageItem(STORAGE_KEYS.USER_TYPE, session.userType);
|
|
188
|
-
setStorageItem(STORAGE_KEYS.LAST_ACTIVITY, metadata.lastActivity);
|
|
189
|
-
return { success: true, data: undefined, error: null };
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Loads the session from storage
|
|
193
|
-
*
|
|
194
|
-
* @returns {StorageResult<SessionData>} The loaded session data or error
|
|
195
|
-
* @example
|
|
196
|
-
* ```typescript
|
|
197
|
-
* const result = loadSession();
|
|
198
|
-
* if (result.success && result.data) {
|
|
199
|
-
* const { session, messages } = result.data;
|
|
200
|
-
* // Restore session...
|
|
201
|
-
* }
|
|
202
|
-
* ```
|
|
203
|
-
*/
|
|
204
|
-
export function loadSession() {
|
|
205
|
-
const serialized = getStorageItem(STORAGE_KEYS.SESSION);
|
|
206
|
-
if (!serialized) {
|
|
207
|
-
return { success: false, data: null, error: 'No session found in storage' };
|
|
208
|
-
}
|
|
209
|
-
const data = safeJsonParse(serialized);
|
|
210
|
-
if (!data) {
|
|
211
|
-
return { success: false, data: null, error: 'Failed to parse session data' };
|
|
212
|
-
}
|
|
213
|
-
// Validate session has not expired
|
|
214
|
-
if (data.session.expiresAt) {
|
|
215
|
-
const expiresAt = new Date(data.session.expiresAt);
|
|
216
|
-
if (expiresAt < new Date()) {
|
|
217
|
-
clearSession();
|
|
218
|
-
return { success: false, data: null, error: 'Session has expired' };
|
|
219
|
-
}
|
|
220
|
-
}
|
|
221
|
-
// Update last activity
|
|
222
|
-
const updatedMetadata = {
|
|
223
|
-
...data.metadata,
|
|
224
|
-
lastActivity: new Date().toISOString(),
|
|
225
|
-
};
|
|
226
|
-
// Silently update last activity in storage
|
|
227
|
-
const updatedData = { ...data, metadata: updatedMetadata };
|
|
228
|
-
const serializedUpdated = safeJsonStringify(updatedData);
|
|
229
|
-
if (serializedUpdated) {
|
|
230
|
-
setStorageItem(STORAGE_KEYS.SESSION, serializedUpdated);
|
|
231
|
-
}
|
|
232
|
-
return { success: true, data: updatedData, error: null };
|
|
233
|
-
}
|
|
234
|
-
/**
|
|
235
|
-
* Clears all session data from storage
|
|
236
|
-
*
|
|
237
|
-
* @returns {boolean} True if successful
|
|
238
|
-
* @example
|
|
239
|
-
* ```typescript
|
|
240
|
-
* clearSession(); // Logs out the user
|
|
241
|
-
* ```
|
|
242
|
-
*/
|
|
243
|
-
export function clearSession() {
|
|
244
|
-
const keysToRemove = [
|
|
245
|
-
STORAGE_KEYS.SESSION,
|
|
246
|
-
STORAGE_KEYS.USER_TYPE,
|
|
247
|
-
STORAGE_KEYS.MESSAGES,
|
|
248
|
-
STORAGE_KEYS.PREFERENCES,
|
|
249
|
-
STORAGE_KEYS.LAST_ACTIVITY,
|
|
250
|
-
STORAGE_KEYS.SESSION_METADATA,
|
|
251
|
-
];
|
|
252
|
-
let allSuccess = true;
|
|
253
|
-
for (const key of keysToRemove) {
|
|
254
|
-
if (!removeStorageItem(key)) {
|
|
255
|
-
allSuccess = false;
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
// Also clear memory storage
|
|
259
|
-
memoryStorage.clear();
|
|
260
|
-
return allSuccess;
|
|
261
|
-
}
|
|
262
|
-
/**
|
|
263
|
-
* Gets the user type from storage
|
|
264
|
-
* Returns 'anonymous' if no user type is stored or on error
|
|
265
|
-
*
|
|
266
|
-
* @returns {UserType} The stored user type or 'anonymous'
|
|
267
|
-
* @example
|
|
268
|
-
* ```typescript
|
|
269
|
-
* const userType = getUserType();
|
|
270
|
-
* if (userType === 'pro') {
|
|
271
|
-
* // Show pro features
|
|
272
|
-
* }
|
|
273
|
-
* ```
|
|
274
|
-
*/
|
|
275
|
-
export function getUserType() {
|
|
276
|
-
const stored = getStorageItem(STORAGE_KEYS.USER_TYPE);
|
|
277
|
-
if (stored && VALID_USER_TYPES.includes(stored)) {
|
|
278
|
-
return stored;
|
|
279
|
-
}
|
|
280
|
-
// Try to infer from session
|
|
281
|
-
const sessionResult = loadSession();
|
|
282
|
-
if (sessionResult.success && sessionResult.data) {
|
|
283
|
-
const sessionType = sessionResult.data.session.userType;
|
|
284
|
-
if (VALID_USER_TYPES.includes(sessionType)) {
|
|
285
|
-
return sessionType;
|
|
286
|
-
}
|
|
287
|
-
}
|
|
288
|
-
return 'anonymous';
|
|
289
|
-
}
|
|
290
|
-
/**
|
|
291
|
-
* Loads session metadata without loading the full session
|
|
292
|
-
*
|
|
293
|
-
* @returns {SessionMetadata | null} The metadata or null if not found
|
|
294
|
-
*/
|
|
295
|
-
function loadSessionMetadata() {
|
|
296
|
-
const sessionResult = loadSession();
|
|
297
|
-
if (sessionResult.success && sessionResult.data) {
|
|
298
|
-
return sessionResult.data.metadata;
|
|
299
|
-
}
|
|
300
|
-
return null;
|
|
301
|
-
}
|
|
302
|
-
/**
|
|
303
|
-
* Saves messages to session storage
|
|
304
|
-
*
|
|
305
|
-
* @param {TypedMessage[]} messages - Messages to save
|
|
306
|
-
* @returns {StorageResult<void>} Result of the operation
|
|
307
|
-
*/
|
|
308
|
-
export function saveMessages(messages) {
|
|
309
|
-
const serialized = safeJsonStringify(messages);
|
|
310
|
-
if (!serialized) {
|
|
311
|
-
return { success: false, data: null, error: 'Failed to serialize messages' };
|
|
312
|
-
}
|
|
313
|
-
if (!setStorageItem(STORAGE_KEYS.MESSAGES, serialized)) {
|
|
314
|
-
return { success: false, data: null, error: 'Failed to write messages to storage' };
|
|
315
|
-
}
|
|
316
|
-
// Update message count in session metadata
|
|
317
|
-
const sessionResult = loadSession();
|
|
318
|
-
if (sessionResult.success && sessionResult.data) {
|
|
319
|
-
const { session, metadata, preferences } = sessionResult.data;
|
|
320
|
-
saveSession(session, {
|
|
321
|
-
messages,
|
|
322
|
-
preferences,
|
|
323
|
-
});
|
|
324
|
-
}
|
|
325
|
-
return { success: true, data: undefined, error: null };
|
|
326
|
-
}
|
|
327
|
-
/**
|
|
328
|
-
* Loads messages from session storage
|
|
329
|
-
*
|
|
330
|
-
* @returns {StorageResult<TypedMessage[]>} The loaded messages or error
|
|
331
|
-
*/
|
|
332
|
-
export function loadMessages() {
|
|
333
|
-
const serialized = getStorageItem(STORAGE_KEYS.MESSAGES);
|
|
334
|
-
if (!serialized) {
|
|
335
|
-
return { success: false, data: null, error: 'No messages found in storage' };
|
|
336
|
-
}
|
|
337
|
-
const messages = safeJsonParse(serialized, []);
|
|
338
|
-
if (!messages) {
|
|
339
|
-
return { success: false, data: null, error: 'Failed to parse messages' };
|
|
340
|
-
}
|
|
341
|
-
return { success: true, data: messages, error: null };
|
|
342
|
-
}
|
|
343
|
-
/**
|
|
344
|
-
* Saves user preferences to storage
|
|
345
|
-
*
|
|
346
|
-
* @param {Record<string, unknown>} preferences - Preferences to save
|
|
347
|
-
* @returns {StorageResult<void>} Result of the operation
|
|
348
|
-
*/
|
|
349
|
-
export function savePreferences(preferences) {
|
|
350
|
-
const serialized = safeJsonStringify(preferences);
|
|
351
|
-
if (!serialized) {
|
|
352
|
-
return { success: false, data: null, error: 'Failed to serialize preferences' };
|
|
353
|
-
}
|
|
354
|
-
if (!setStorageItem(STORAGE_KEYS.PREFERENCES, serialized)) {
|
|
355
|
-
return { success: false, data: null, error: 'Failed to write preferences to storage' };
|
|
356
|
-
}
|
|
357
|
-
return { success: true, data: undefined, error: null };
|
|
358
|
-
}
|
|
359
|
-
/**
|
|
360
|
-
* Loads user preferences from storage
|
|
361
|
-
*
|
|
362
|
-
* @returns {StorageResult<Record<string, unknown>>} The loaded preferences or error
|
|
363
|
-
*/
|
|
364
|
-
export function loadPreferences() {
|
|
365
|
-
const serialized = getStorageItem(STORAGE_KEYS.PREFERENCES);
|
|
366
|
-
if (!serialized) {
|
|
367
|
-
return { success: false, data: null, error: 'No preferences found in storage' };
|
|
368
|
-
}
|
|
369
|
-
const preferences = safeJsonParse(serialized, {});
|
|
370
|
-
if (!preferences) {
|
|
371
|
-
return { success: false, data: null, error: 'Failed to parse preferences' };
|
|
372
|
-
}
|
|
373
|
-
return { success: true, data: preferences, error: null };
|
|
374
|
-
}
|
|
375
|
-
/**
|
|
376
|
-
* Gets the timestamp of the last user activity
|
|
377
|
-
*
|
|
378
|
-
* @returns {Date | null} The last activity date or null if not found
|
|
379
|
-
*/
|
|
380
|
-
export function getLastActivity() {
|
|
381
|
-
const stored = getStorageItem(STORAGE_KEYS.LAST_ACTIVITY);
|
|
382
|
-
if (!stored) {
|
|
383
|
-
return null;
|
|
384
|
-
}
|
|
385
|
-
try {
|
|
386
|
-
const date = new Date(stored);
|
|
387
|
-
return isNaN(date.getTime()) ? null : date;
|
|
388
|
-
}
|
|
389
|
-
catch {
|
|
390
|
-
return null;
|
|
391
|
-
}
|
|
392
|
-
}
|
|
393
|
-
/**
|
|
394
|
-
* Updates the last activity timestamp to now
|
|
395
|
-
*
|
|
396
|
-
* @returns {boolean} True if successful
|
|
397
|
-
*/
|
|
398
|
-
export function updateLastActivity() {
|
|
399
|
-
return setStorageItem(STORAGE_KEYS.LAST_ACTIVITY, new Date().toISOString());
|
|
400
|
-
}
|
|
401
|
-
/**
|
|
402
|
-
* Checks if there is an active session in storage
|
|
403
|
-
*
|
|
404
|
-
* @returns {boolean} True if a valid session exists
|
|
405
|
-
*/
|
|
406
|
-
export function hasActiveSession() {
|
|
407
|
-
const result = loadSession();
|
|
408
|
-
return result.success;
|
|
409
|
-
}
|
|
410
|
-
/**
|
|
411
|
-
* Type guard to check if a value is a valid UserType
|
|
412
|
-
*
|
|
413
|
-
* @param {unknown} value - The value to check
|
|
414
|
-
* @returns {boolean} True if the value is a valid UserType
|
|
415
|
-
*/
|
|
416
|
-
export function isUserType(value) {
|
|
417
|
-
return typeof value === 'string' && VALID_USER_TYPES.includes(value);
|
|
418
|
-
}
|
|
419
|
-
// Default export
|
|
420
|
-
export default {
|
|
421
|
-
STORAGE_KEYS,
|
|
422
|
-
VALID_USER_TYPES,
|
|
423
|
-
saveSession,
|
|
424
|
-
loadSession,
|
|
425
|
-
clearSession,
|
|
426
|
-
getUserType,
|
|
427
|
-
saveMessages,
|
|
428
|
-
loadMessages,
|
|
429
|
-
savePreferences,
|
|
430
|
-
loadPreferences,
|
|
431
|
-
getLastActivity,
|
|
432
|
-
updateLastActivity,
|
|
433
|
-
hasActiveSession,
|
|
434
|
-
isUserType,
|
|
435
|
-
};
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gizzi Workspace File Watcher
|
|
3
|
-
*
|
|
4
|
-
* Monitors agent workspace files for changes and triggers context refresh.
|
|
5
|
-
*/
|
|
6
|
-
import type { FileSystem } from '../workspace/loader';
|
|
7
|
-
export interface FileChange {
|
|
8
|
-
path: string;
|
|
9
|
-
type: 'created' | 'modified' | 'deleted';
|
|
10
|
-
previousModTime?: Date;
|
|
11
|
-
currentModTime?: Date;
|
|
12
|
-
}
|
|
13
|
-
export interface WatcherOptions {
|
|
14
|
-
pollIntervalMs: number;
|
|
15
|
-
onChange: (changes: FileChange[]) => void;
|
|
16
|
-
onError?: (error: Error) => void;
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* Workspace File Watcher for Gizzi
|
|
20
|
-
*/
|
|
21
|
-
export declare class WorkspaceWatcher {
|
|
22
|
-
private agentId;
|
|
23
|
-
private basePath;
|
|
24
|
-
private fs;
|
|
25
|
-
private options;
|
|
26
|
-
private intervalId;
|
|
27
|
-
private watchedFiles;
|
|
28
|
-
private isWatching;
|
|
29
|
-
constructor(agentId: string, basePath: string, fs: FileSystem, options?: Partial<WatcherOptions>);
|
|
30
|
-
/**
|
|
31
|
-
* Start watching for changes
|
|
32
|
-
*/
|
|
33
|
-
start(): Promise<void>;
|
|
34
|
-
/**
|
|
35
|
-
* Stop watching
|
|
36
|
-
*/
|
|
37
|
-
stop(): void;
|
|
38
|
-
/**
|
|
39
|
-
* Get current watch status
|
|
40
|
-
*/
|
|
41
|
-
getStatus(): {
|
|
42
|
-
isWatching: boolean;
|
|
43
|
-
filesWatched: number;
|
|
44
|
-
};
|
|
45
|
-
/**
|
|
46
|
-
* Force a manual refresh
|
|
47
|
-
*/
|
|
48
|
-
refresh(): Promise<FileChange[]>;
|
|
49
|
-
/**
|
|
50
|
-
* Scan workspace for files
|
|
51
|
-
*/
|
|
52
|
-
private scanWorkspace;
|
|
53
|
-
/**
|
|
54
|
-
* Check for changes
|
|
55
|
-
*/
|
|
56
|
-
private checkForChanges;
|
|
57
|
-
}
|
|
58
|
-
/**
|
|
59
|
-
* Get or create a watcher for an agent
|
|
60
|
-
*/
|
|
61
|
-
export declare function getWorkspaceWatcher(agentId: string, basePath: string, fs: FileSystem, options?: Partial<WatcherOptions>): WorkspaceWatcher;
|
|
62
|
-
/**
|
|
63
|
-
* Stop all watchers
|
|
64
|
-
*/
|
|
65
|
-
export declare function stopAllWatchers(): void;
|
|
66
|
-
export declare const workspaceWatcher: {
|
|
67
|
-
watchers: Map<string, WorkspaceWatcher>;
|
|
68
|
-
getWatcher: typeof getWorkspaceWatcher;
|
|
69
|
-
stopAll: typeof stopAllWatchers;
|
|
70
|
-
};
|
|
@@ -1,191 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Gizzi Workspace File Watcher
|
|
3
|
-
*
|
|
4
|
-
* Monitors agent workspace files for changes and triggers context refresh.
|
|
5
|
-
*/
|
|
6
|
-
/**
|
|
7
|
-
* Workspace File Watcher for Gizzi
|
|
8
|
-
*/
|
|
9
|
-
export class WorkspaceWatcher {
|
|
10
|
-
constructor(agentId, basePath, fs, options = {}) {
|
|
11
|
-
this.intervalId = null;
|
|
12
|
-
this.watchedFiles = new Map();
|
|
13
|
-
this.isWatching = false;
|
|
14
|
-
this.agentId = agentId;
|
|
15
|
-
this.basePath = basePath;
|
|
16
|
-
this.fs = fs;
|
|
17
|
-
this.options = {
|
|
18
|
-
pollIntervalMs: 5000,
|
|
19
|
-
onChange: () => { },
|
|
20
|
-
...options,
|
|
21
|
-
};
|
|
22
|
-
}
|
|
23
|
-
/**
|
|
24
|
-
* Start watching for changes
|
|
25
|
-
*/
|
|
26
|
-
async start() {
|
|
27
|
-
if (this.isWatching) {
|
|
28
|
-
console.log(`[WorkspaceWatcher] Already watching ${this.agentId}`);
|
|
29
|
-
return;
|
|
30
|
-
}
|
|
31
|
-
// Initial scan
|
|
32
|
-
try {
|
|
33
|
-
await this.scanWorkspace();
|
|
34
|
-
}
|
|
35
|
-
catch (error) {
|
|
36
|
-
console.error(`[WorkspaceWatcher] Initial scan failed:`, error);
|
|
37
|
-
this.options.onError?.(error);
|
|
38
|
-
return;
|
|
39
|
-
}
|
|
40
|
-
// Start polling
|
|
41
|
-
this.isWatching = true;
|
|
42
|
-
this.intervalId = setInterval(() => {
|
|
43
|
-
this.checkForChanges().catch((error) => {
|
|
44
|
-
console.error(`[WorkspaceWatcher] Check failed:`, error);
|
|
45
|
-
this.options.onError?.(error);
|
|
46
|
-
});
|
|
47
|
-
}, this.options.pollIntervalMs);
|
|
48
|
-
console.log(`[WorkspaceWatcher] Started watching ${this.agentId} (${this.options.pollIntervalMs}ms interval)`);
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Stop watching
|
|
52
|
-
*/
|
|
53
|
-
stop() {
|
|
54
|
-
if (this.intervalId) {
|
|
55
|
-
clearInterval(this.intervalId);
|
|
56
|
-
this.intervalId = null;
|
|
57
|
-
}
|
|
58
|
-
this.isWatching = false;
|
|
59
|
-
console.log(`[WorkspaceWatcher] Stopped watching ${this.agentId}`);
|
|
60
|
-
}
|
|
61
|
-
/**
|
|
62
|
-
* Get current watch status
|
|
63
|
-
*/
|
|
64
|
-
getStatus() {
|
|
65
|
-
return {
|
|
66
|
-
isWatching: this.isWatching,
|
|
67
|
-
filesWatched: this.watchedFiles.size,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Force a manual refresh
|
|
72
|
-
*/
|
|
73
|
-
async refresh() {
|
|
74
|
-
return this.checkForChanges();
|
|
75
|
-
}
|
|
76
|
-
/**
|
|
77
|
-
* Scan workspace for files
|
|
78
|
-
*/
|
|
79
|
-
async scanWorkspace() {
|
|
80
|
-
this.watchedFiles.clear();
|
|
81
|
-
const entries = await this.fs.listDirectory(this.basePath);
|
|
82
|
-
for (const entry of entries) {
|
|
83
|
-
if (entry.type === 'file') {
|
|
84
|
-
const filePath = `${this.basePath}/${entry.name}`;
|
|
85
|
-
try {
|
|
86
|
-
const content = await this.fs.readFile(filePath);
|
|
87
|
-
this.watchedFiles.set(entry.name, {
|
|
88
|
-
path: entry.name,
|
|
89
|
-
lastModified: new Date(), // We don't have actual mtime from FileSystem interface
|
|
90
|
-
size: content.length,
|
|
91
|
-
});
|
|
92
|
-
}
|
|
93
|
-
catch {
|
|
94
|
-
// Skip files we can't read
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
/**
|
|
100
|
-
* Check for changes
|
|
101
|
-
*/
|
|
102
|
-
async checkForChanges() {
|
|
103
|
-
const changes = [];
|
|
104
|
-
const currentFiles = new Map();
|
|
105
|
-
try {
|
|
106
|
-
const entries = await this.fs.listDirectory(this.basePath);
|
|
107
|
-
for (const entry of entries) {
|
|
108
|
-
if (entry.type !== 'file')
|
|
109
|
-
continue;
|
|
110
|
-
const filePath = `${this.basePath}/${entry.name}`;
|
|
111
|
-
try {
|
|
112
|
-
const content = await this.fs.readFile(filePath);
|
|
113
|
-
const previousFile = this.watchedFiles.get(entry.name);
|
|
114
|
-
currentFiles.set(entry.name, {
|
|
115
|
-
path: entry.name,
|
|
116
|
-
lastModified: new Date(),
|
|
117
|
-
size: content.length,
|
|
118
|
-
});
|
|
119
|
-
if (!previousFile) {
|
|
120
|
-
// New file
|
|
121
|
-
changes.push({
|
|
122
|
-
path: entry.name,
|
|
123
|
-
type: 'created',
|
|
124
|
-
currentModTime: new Date(),
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
else if (content.length !== previousFile.size) {
|
|
128
|
-
// Modified file (using size as proxy for modification)
|
|
129
|
-
changes.push({
|
|
130
|
-
path: entry.name,
|
|
131
|
-
type: 'modified',
|
|
132
|
-
previousModTime: previousFile.lastModified,
|
|
133
|
-
currentModTime: new Date(),
|
|
134
|
-
});
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
catch {
|
|
138
|
-
// Skip files we can't read
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
// Check for deleted files
|
|
142
|
-
for (const [name, file] of this.watchedFiles) {
|
|
143
|
-
if (!currentFiles.has(name)) {
|
|
144
|
-
changes.push({
|
|
145
|
-
path: name,
|
|
146
|
-
type: 'deleted',
|
|
147
|
-
previousModTime: file.lastModified,
|
|
148
|
-
});
|
|
149
|
-
}
|
|
150
|
-
}
|
|
151
|
-
// Update state
|
|
152
|
-
this.watchedFiles = currentFiles;
|
|
153
|
-
// Notify if changes detected
|
|
154
|
-
if (changes.length > 0) {
|
|
155
|
-
console.log(`[WorkspaceWatcher] Detected ${changes.length} changes in ${this.agentId}:`, changes.map(c => `${c.type}:${c.path}`).join(', '));
|
|
156
|
-
this.options.onChange(changes);
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
catch (error) {
|
|
160
|
-
console.error(`[WorkspaceWatcher] Failed to check for changes:`, error);
|
|
161
|
-
this.options.onError?.(error);
|
|
162
|
-
}
|
|
163
|
-
return changes;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
// Global watcher registry
|
|
167
|
-
const watchers = new Map();
|
|
168
|
-
/**
|
|
169
|
-
* Get or create a watcher for an agent
|
|
170
|
-
*/
|
|
171
|
-
export function getWorkspaceWatcher(agentId, basePath, fs, options) {
|
|
172
|
-
if (!watchers.has(agentId)) {
|
|
173
|
-
watchers.set(agentId, new WorkspaceWatcher(agentId, basePath, fs, options));
|
|
174
|
-
}
|
|
175
|
-
return watchers.get(agentId);
|
|
176
|
-
}
|
|
177
|
-
/**
|
|
178
|
-
* Stop all watchers
|
|
179
|
-
*/
|
|
180
|
-
export function stopAllWatchers() {
|
|
181
|
-
for (const [agentId, watcher] of watchers) {
|
|
182
|
-
watcher.stop();
|
|
183
|
-
}
|
|
184
|
-
watchers.clear();
|
|
185
|
-
}
|
|
186
|
-
// Export singleton for global access
|
|
187
|
-
export const workspaceWatcher = {
|
|
188
|
-
watchers,
|
|
189
|
-
getWatcher: getWorkspaceWatcher,
|
|
190
|
-
stopAll: stopAllWatchers,
|
|
191
|
-
};
|