@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.
Files changed (158) hide show
  1. package/bin/gizzi +4 -0
  2. package/bin/gizzi-ink +5 -0
  3. package/package.json +137 -31
  4. package/src/Tool.ts +26 -0
  5. package/src/bootstrap/state.ts +165 -322
  6. package/src/commands.ts +209 -0
  7. package/src/context/QueuedMessageContext.tsx +63 -0
  8. package/src/context/fpsMetrics.tsx +30 -0
  9. package/src/context/mailbox.tsx +38 -0
  10. package/src/context/modalContext.tsx +58 -0
  11. package/src/context/notifications.tsx +240 -0
  12. package/src/context/overlayContext.tsx +151 -0
  13. package/src/context/promptOverlayContext.tsx +125 -0
  14. package/src/context/stats.tsx +220 -0
  15. package/src/context/voice.tsx +88 -0
  16. package/src/hooks/useCanUseTool.ts +11 -0
  17. package/src/hooks/useExitOnCtrlCD.ts +40 -187
  18. package/src/hooks/useExitOnCtrlCDWithKeybindings.ts +68 -0
  19. package/src/hooks/useKeybinding.ts +68 -209
  20. package/src/hooks/useTerminalSize.ts +31 -99
  21. package/src/hooks.ts +37 -0
  22. package/src/ink.ts +204 -0
  23. package/src/main.ts +7 -0
  24. package/src/types/command.ts +216 -0
  25. package/src/types/connectorText.ts +39 -0
  26. package/src/types/fileSuggestion.ts +15 -0
  27. package/src/types/generated/events_mono/claude_code/v1/claude_code_internal_event.ts +865 -0
  28. package/src/types/generated/events_mono/common/v1/auth.ts +100 -0
  29. package/src/types/generated/events_mono/growthbook/v1/growthbook_experiment_event.ts +223 -0
  30. package/src/types/generated/google/protobuf/timestamp.ts +187 -0
  31. package/src/types/hooks.ts +319 -0
  32. package/src/types/ids.ts +44 -0
  33. package/src/types/logs.ts +331 -0
  34. package/src/types/merged/index.ts +5 -0
  35. package/src/types/merged/message.ts +552 -0
  36. package/src/types/message.ts +927 -186
  37. package/src/types/messageQueueTypes.ts +21 -0
  38. package/src/types/notebook.ts +72 -0
  39. package/src/types/permissions.ts +447 -0
  40. package/src/types/plugin.ts +363 -0
  41. package/src/types/statusLine.ts +15 -0
  42. package/src/types/textInputTypes.ts +387 -0
  43. package/src/types/tools.ts +149 -0
  44. package/src/types/utils.ts +20 -0
  45. package/src/utils/advisor.ts +12 -0
  46. package/src/utils/api.ts +29 -0
  47. package/src/utils/array.ts +7 -0
  48. package/src/utils/attachments.ts +60 -0
  49. package/src/utils/auth.ts +3 -0
  50. package/src/utils/claudeInChrome/chromeNativeHost.ts +15 -0
  51. package/src/utils/claudeInChrome/common.ts +12 -0
  52. package/src/utils/claudeInChrome/mcpServer.ts +15 -0
  53. package/src/utils/computerUse/common.ts +19 -0
  54. package/src/utils/computerUse/mcpServer.ts +15 -0
  55. package/src/utils/config.ts +35 -0
  56. package/src/utils/context.ts +19 -0
  57. package/src/utils/cwd.ts +3 -0
  58. package/src/utils/debug.ts +3 -0
  59. package/src/utils/earlyInput.ts +7 -0
  60. package/src/utils/effort.ts +13 -0
  61. package/src/utils/embeddedTools.ts +12 -0
  62. package/src/utils/envUtils.ts +3 -0
  63. package/src/utils/errors.ts +3 -0
  64. package/src/utils/execFileNoThrow.ts +24 -0
  65. package/src/utils/feature-flags.ts +112 -0
  66. package/src/utils/file.ts +3 -0
  67. package/src/utils/fileHistory.ts +17 -0
  68. package/src/utils/fingerprint.ts +7 -0
  69. package/src/utils/format.ts +75 -305
  70. package/src/utils/frontmatterParser.ts +33 -0
  71. package/src/utils/fsOperations.ts +31 -0
  72. package/src/utils/fullscreen.ts +40 -350
  73. package/src/utils/git.ts +15 -0
  74. package/src/utils/imageResizer.ts +30 -0
  75. package/src/utils/lazySchema.ts +9 -0
  76. package/src/utils/log.ts +3 -0
  77. package/src/utils/markdownConfigLoader.ts +12 -0
  78. package/src/utils/messages.ts +13 -0
  79. package/src/utils/migration.ts +137 -0
  80. package/src/utils/model/providers.ts +15 -0
  81. package/src/utils/path.ts +3 -0
  82. package/src/utils/permissions/PermissionResult.ts +14 -0
  83. package/src/utils/permissions/autoModeState.ts +12 -0
  84. package/src/utils/permissions/filesystem.ts +12 -0
  85. package/src/utils/plugins/loadPluginOutputStyles.ts +12 -0
  86. package/src/utils/plugins/schemas.ts +25 -0
  87. package/src/utils/process.ts +16 -0
  88. package/src/utils/sandbox/sandbox-adapter.ts +19 -0
  89. package/src/utils/sessionStorage.ts +238 -472
  90. package/src/utils/settings/constants.ts +10 -0
  91. package/src/utils/settings/settings.ts +19 -0
  92. package/src/utils/settings/types.ts +18 -0
  93. package/src/utils/shell/shellToolUtils.ts +9 -0
  94. package/src/utils/sinks.ts +11 -0
  95. package/src/utils/sleep.ts +7 -0
  96. package/src/utils/sliceAnsi.ts +7 -0
  97. package/src/utils/slowOperations.ts +3 -0
  98. package/src/utils/startupProfiler.ts +11 -0
  99. package/src/utils/stringUtils.ts +106 -0
  100. package/src/utils/systemPromptType.ts +9 -0
  101. package/src/utils/teleport/api.ts +15 -0
  102. package/src/utils/textHighlighting.ts +16 -0
  103. package/src/utils/theme.ts +17 -0
  104. package/src/utils/thinking.ts +58 -0
  105. package/src/utils/tokens.ts +11 -0
  106. package/src/utils/toolResultStorage.ts +17 -0
  107. package/src/utils/worktreeModeEnabled.ts +7 -0
  108. package/WORKSPACE_INTEGRATION.md +0 -290
  109. package/chat-sessions/sessions-index.json +0 -98
  110. package/package.json.original +0 -31
  111. package/package.json.publish +0 -47
  112. package/src/bootstrap/state.d.ts +0 -169
  113. package/src/bootstrap/state.js +0 -261
  114. package/src/context/pack-builder.d.ts +0 -24
  115. package/src/context/pack-builder.js +0 -281
  116. package/src/hooks/useExitOnCtrlCD.d.ts +0 -86
  117. package/src/hooks/useExitOnCtrlCD.js +0 -130
  118. package/src/hooks/useKeybinding.d.ts +0 -89
  119. package/src/hooks/useKeybinding.js +0 -163
  120. package/src/hooks/useTerminalSize.d.ts +0 -41
  121. package/src/hooks/useTerminalSize.js +0 -90
  122. package/src/index.d.ts +0 -23
  123. package/src/index.js +0 -24
  124. package/src/runtime/brand/brand.d.ts +0 -488
  125. package/src/runtime/brand/brand.js +0 -464
  126. package/src/runtime/brand/brand.ts +0 -667
  127. package/src/runtime/services/tokenEstimation.d.ts +0 -187
  128. package/src/runtime/services/tokenEstimation.js +0 -423
  129. package/src/runtime/services/tokenEstimation.ts +0 -547
  130. package/src/runtime/tools/Tool.d.ts +0 -239
  131. package/src/runtime/tools/Tool.js +0 -285
  132. package/src/runtime/tools/Tool.ts +0 -524
  133. package/src/scheduler/TaskScheduler.d.ts +0 -98
  134. package/src/scheduler/TaskScheduler.js +0 -201
  135. package/src/scheduler/TaskScheduler.ts +0 -259
  136. package/src/state/AppStateStore.d.ts +0 -347
  137. package/src/state/AppStateStore.js +0 -439
  138. package/src/state/AppStateStore.ts +0 -658
  139. package/src/state/WorkspaceStateStore.d.ts +0 -43
  140. package/src/state/WorkspaceStateStore.js +0 -224
  141. package/src/state/WorkspaceStateStore.ts +0 -297
  142. package/src/types/message.d.ts +0 -190
  143. package/src/types/message.js +0 -77
  144. package/src/utils/format.d.ts +0 -126
  145. package/src/utils/format.js +0 -230
  146. package/src/utils/fullscreen.d.ts +0 -161
  147. package/src/utils/fullscreen.js +0 -277
  148. package/src/utils/sessionStorage.d.ts +0 -210
  149. package/src/utils/sessionStorage.js +0 -435
  150. package/src/watcher/WorkspaceWatcher.d.ts +0 -70
  151. package/src/watcher/WorkspaceWatcher.js +0 -191
  152. package/src/watcher/WorkspaceWatcher.ts +0 -251
  153. package/src/workspace/loader.d.ts +0 -30
  154. package/src/workspace/loader.js +0 -117
  155. package/src/workspace/types.d.ts +0 -91
  156. package/src/workspace/types.js +0 -7
  157. package/threads/thread_1775361175022.json +0 -9
  158. package/tsconfig.json +0 -14
@@ -1,281 +0,0 @@
1
- /**
2
- * Gizzi Context Pack Builder
3
- *
4
- * Builds structured context packs from workspace files
5
- * Production-quality implementation matching Allternit platform
6
- */
7
- // ============================================================================
8
- // File Classification
9
- // ============================================================================
10
- export function classifyFile(filePath) {
11
- const lower = filePath.toLowerCase();
12
- if (lower.endsWith('manifest.json'))
13
- return 'manifest';
14
- if (lower.includes('/brain/'))
15
- return 'brain';
16
- if (lower.includes('/memory/'))
17
- return 'memory';
18
- if (lower.endsWith('soul.md'))
19
- return 'soul';
20
- if (lower.includes('/identity/identity.md'))
21
- return 'identity';
22
- if (lower.includes('/identity/user.md'))
23
- return 'user';
24
- if (lower.includes('/identity/voice.md'))
25
- return 'voice';
26
- if (lower.includes('/identity/policy.md'))
27
- return 'policy';
28
- if (lower.includes('/governance/playbook.md'))
29
- return 'playbook';
30
- if (lower.includes('/governance/tools.md'))
31
- return 'tools';
32
- if (lower.includes('/governance/heartbeat.md'))
33
- return 'heartbeat';
34
- if (lower.includes('/governance/system.md'))
35
- return 'system';
36
- if (lower.includes('/governance/channels.md'))
37
- return 'channels';
38
- if (lower.includes('/skills/'))
39
- return 'skill';
40
- if (lower.includes('/business/'))
41
- return 'business';
42
- if (lower.endsWith('.json') || lower.endsWith('.yaml') || lower.endsWith('.yml'))
43
- return 'config';
44
- return 'knowledge';
45
- }
46
- // ============================================================================
47
- // SOUL.md Parser
48
- // ============================================================================
49
- export function parseSoulMd(content) {
50
- const lines = content.split('\n');
51
- const trustTiers = {
52
- tier1: { level: 1, name: 'Foundation', rules: [], enforce: 'always' },
53
- tier2: { level: 2, name: 'Contextual', rules: [], enforce: 'contextual' },
54
- tier3: { level: 3, name: 'Permission Required', rules: [], enforce: 'permission' },
55
- };
56
- const identity = {
57
- personalityTraits: [],
58
- };
59
- let currentTier = null;
60
- let inSelfAwareness = false;
61
- for (const line of lines) {
62
- const trimmed = line.trim();
63
- if (trimmed.match(/^#+\s*Tier\s*1/i)) {
64
- currentTier = 1;
65
- }
66
- else if (trimmed.match(/^#+\s*Tier\s*2/i)) {
67
- currentTier = 2;
68
- }
69
- else if (trimmed.match(/^#+\s*Tier\s*3/i)) {
70
- currentTier = 3;
71
- }
72
- else if (trimmed.match(/^#+\s*Self-Awareness/i)) {
73
- inSelfAwareness = true;
74
- currentTier = null;
75
- }
76
- if (currentTier && trimmed.match(/^[-\*✅]\s+/)) {
77
- const rule = trimmed.replace(/^[-\*✅]\s+/, '');
78
- trustTiers[`tier${currentTier}`].rules.push(rule);
79
- }
80
- if (inSelfAwareness && trimmed.startsWith('I am')) {
81
- identity.backstory = trimmed;
82
- }
83
- }
84
- return { trustTiers, identity };
85
- }
86
- // ============================================================================
87
- // HEARTBEAT.md Parser
88
- // ============================================================================
89
- export function parseHeartbeatMd(content) {
90
- const lines = content.split('\n');
91
- const tasks = [];
92
- let currentFrequency = 'daily';
93
- for (const line of lines) {
94
- const trimmed = line.trim();
95
- if (trimmed.match(/^#+\s*Daily/i)) {
96
- currentFrequency = 'daily';
97
- }
98
- else if (trimmed.match(/^#+\s*Weekly/i)) {
99
- currentFrequency = 'weekly';
100
- }
101
- else if (trimmed.match(/^#+\s*Monthly/i)) {
102
- currentFrequency = 'monthly';
103
- }
104
- else if (trimmed.match(/^#+\s*On\s+Session\s+Start/i)) {
105
- currentFrequency = 'on-session-start';
106
- }
107
- const taskMatch = trimmed.match(/^-\s*\[([ xX])\]\s*(.+)/);
108
- if (taskMatch) {
109
- tasks.push({
110
- id: `task-${Date.now()}-${tasks.length}`,
111
- frequency: currentFrequency,
112
- action: taskMatch[2].trim(),
113
- lastExecuted: taskMatch[1].toLowerCase() === 'x' ? new Date().toISOString() : undefined,
114
- });
115
- }
116
- }
117
- return tasks;
118
- }
119
- // ============================================================================
120
- // System Prompt Builder
121
- // ============================================================================
122
- export function buildSystemPrompt(pack) {
123
- const sections = [];
124
- // Identity
125
- sections.push(`# Agent Identity
126
-
127
- You are ${pack.identity.name}.
128
-
129
- ## Purpose
130
- ${pack.identity.purpose}
131
-
132
- ## Backstory
133
- ${pack.identity.backstory}
134
-
135
- ## Personality Traits
136
- ${pack.identity.personalityTraits.map(t => `- ${t}`).join('\n')}`);
137
- // Trust Tiers (CRITICAL)
138
- sections.push(`# Trust & Safety (MUST FOLLOW)
139
-
140
- ## Tier 1 - Foundation (ALWAYS APPLY)
141
- ${pack.trustTiers.tier1.rules.map(r => `- ${r}`).join('\n')}
142
-
143
- ## Tier 2 - Contextual (APPLY WHEN RELEVANT)
144
- ${pack.trustTiers.tier2.rules.map(r => `- ${r}`).join('\n')}
145
-
146
- ## Tier 3 - Permission Required (ASK USER FIRST)
147
- ${pack.trustTiers.tier3.rules.map(r => `- ${r}`).join('\n')}
148
-
149
- ### BEFORE ANY ACTION:
150
- 1. Check if action violates Tier 1 → NEVER DO
151
- 2. Check if action matches Tier 2 → APPLY IF CONTEXT FITS
152
- 3. Check if action requires Tier 3 → ASK USER PERMISSION`);
153
- // Governance
154
- if (pack.governance.playbook) {
155
- sections.push(`# Governance & Procedures
156
-
157
- ${pack.governance.playbook}`);
158
- }
159
- // Tools
160
- if (pack.governance.availableTools.length > 0) {
161
- sections.push(`# Available Tools
162
-
163
- ${pack.governance.availableTools.map(t => `- **${t.name}**: ${t.description}${t.requiresPermission ? ' (Requires Permission)' : ''}`).join('\n')}`);
164
- }
165
- // Hard Bans
166
- if (pack.governance.hardBans.length > 0) {
167
- sections.push(`# Hard Bans (NEVER DO THESE)
168
-
169
- ${pack.governance.hardBans.map(b => `- ❌ ${b}`).join('\n')}`);
170
- }
171
- // Voice
172
- sections.push(`# Voice & Communication Style
173
-
174
- ${pack.voice.style}
175
-
176
- ## Communication Rules
177
- ${pack.voice.rules.map(r => `- ${r}`).join('\n')}`);
178
- // Memory
179
- if (pack.memory.brain || pack.memory.activeTasks.length > 0) {
180
- sections.push(`# Current Context
181
-
182
- ## Active Tasks
183
- ${pack.memory.activeTasks.map(t => `- ${t}`).join('\n') || 'None'}
184
-
185
- ## Key Lessons
186
- ${pack.memory.lessons.map(l => `- ${l}`).join('\n') || 'None'}`);
187
- }
188
- return sections.join('\n\n---\n\n');
189
- }
190
- export function buildContextPack(options) {
191
- const { sessionId, agentId, agentName, files } = options;
192
- // Parse files
193
- const soulContent = files.has('.allternit/identity/SOUL.md')
194
- ? parseSoulMd(files.get('.allternit/identity/SOUL.md'))
195
- : {
196
- trustTiers: {
197
- tier1: { level: 1, name: 'Foundation', rules: ['Be helpful and accurate'], enforce: 'always' },
198
- tier2: { level: 2, name: 'Contextual', rules: ['Adapt to context'], enforce: 'contextual' },
199
- tier3: { level: 3, name: 'Permission Required', rules: ['Execute code'], enforce: 'permission' },
200
- },
201
- identity: { personalityTraits: ['helpful', 'accurate'] }
202
- };
203
- const heartbeatContent = files.has('.allternit/governance/HEARTBEAT.md')
204
- ? parseHeartbeatMd(files.get('.allternit/governance/HEARTBEAT.md'))
205
- : [];
206
- // Build pack
207
- const pack = {
208
- version: '1.0.0',
209
- agentId,
210
- agentName,
211
- sessionId,
212
- identity: {
213
- name: agentName,
214
- purpose: files.get('.allternit/identity/IDENTITY.md')?.match(/##?\s*Purpose\s*\n([^#]+)/)?.[1]?.trim() || 'Assist the user',
215
- backstory: soulContent.identity.backstory || `I am ${agentName}, an AI assistant.`,
216
- personalityTraits: soulContent.identity.personalityTraits || ['helpful', 'accurate'],
217
- },
218
- trustTiers: soulContent.trustTiers,
219
- governance: {
220
- playbook: files.get('.allternit/governance/PLAYBOOK.md') || '',
221
- availableTools: [], // Would parse from TOOLS.md
222
- hardBans: [],
223
- escalation: [],
224
- },
225
- heartbeat: {
226
- tasks: heartbeatContent,
227
- lastCheck: new Date().toISOString(),
228
- },
229
- memory: {
230
- brain: files.get('.allternit/brain/BRAIN.md') || '',
231
- activeTasks: [],
232
- lessons: [],
233
- userPreferences: {},
234
- },
235
- voice: {
236
- style: files.get('.allternit/identity/VOICE.md') || 'professional and helpful',
237
- tone: { formality: 0.5, enthusiasm: 0.5, empathy: 0.5, directness: 0.5 },
238
- rules: [],
239
- },
240
- systemPrompt: '',
241
- hash: '',
242
- createdAt: new Date().toISOString(),
243
- expiresAt: new Date(Date.now() + 5 * 60 * 1000).toISOString(),
244
- };
245
- // Build system prompt
246
- pack.systemPrompt = buildSystemPrompt(pack);
247
- // Generate hash
248
- pack.hash = generateHash(pack);
249
- return pack;
250
- }
251
- function generateHash(pack) {
252
- const str = JSON.stringify({
253
- agentId: pack.agentId,
254
- trustTiers: pack.trustTiers,
255
- systemPrompt: pack.systemPrompt?.slice(0, 100),
256
- });
257
- let hash = 0;
258
- for (let i = 0; i < str.length; i++) {
259
- const char = str.charCodeAt(i);
260
- hash = ((hash << 5) - hash) + char;
261
- hash = hash & hash;
262
- }
263
- return Math.abs(hash).toString(16).padStart(16, '0');
264
- }
265
- // ============================================================================
266
- // Utility Functions
267
- // ============================================================================
268
- export function getStartupTasks(pack) {
269
- return pack.heartbeat.tasks.filter(t => t.frequency === 'on-session-start');
270
- }
271
- export function requiresPermission(pack, action) {
272
- const actionLower = action.toLowerCase();
273
- // Check Tier 3
274
- if (pack.trustTiers.tier3.rules.some(r => actionLower.includes(r.toLowerCase()))) {
275
- return true;
276
- }
277
- return false;
278
- }
279
- export function shouldRefreshContext(pack) {
280
- return new Date() > new Date(pack.expiresAt);
281
- }
@@ -1,86 +0,0 @@
1
- /**
2
- * @fileoverview Exit handler hook for gizzi-code integration
3
- * @module hooks/useExitOnCtrlCD
4
- *
5
- * Provides a React hook for handling exit key combinations (Ctrl+C and Ctrl+D).
6
- * Commonly used for CLI applications to handle graceful shutdown or exit actions.
7
- */
8
- /**
9
- * Exit handler callback type
10
- * @typedef {Function} ExitHandler
11
- */
12
- export type ExitHandler = () => void | boolean | Promise<void | boolean>;
13
- /**
14
- * Options for the exit handler hook
15
- * @interface UseExitOnCtrlCDOptions
16
- */
17
- export interface UseExitOnCtrlCDOptions {
18
- /** Callback function to execute when exit keys are pressed */
19
- readonly onExit?: ExitHandler;
20
- /** Whether Ctrl+C triggers exit (default: true) */
21
- readonly enableCtrlC?: boolean;
22
- /** Whether Ctrl+D triggers exit (default: true) */
23
- readonly enableCtrlD?: boolean;
24
- /** Whether the exit handler is active (default: true) */
25
- readonly enabled?: boolean;
26
- /** Custom message to display on exit (optional) */
27
- readonly exitMessage?: string;
28
- /** Whether to confirm before exit (default: false) */
29
- readonly confirmBeforeExit?: boolean;
30
- /** Custom confirmation message */
31
- readonly confirmMessage?: string;
32
- }
33
- /**
34
- * React hook for handling Ctrl+C and Ctrl+D exit combinations
35
- *
36
- * Registers keyboard shortcuts for common terminal exit commands and
37
- * executes the provided callback when triggered. Supports optional
38
- * confirmation before exit.
39
- *
40
- * @param {ExitHandler | UseExitOnCtrlCDOptions} handler - Exit callback or options object
41
- * @example
42
- * ```typescript
43
- * // Simple usage with callback
44
- * useExitOnCtrlCD(() => {
45
- * console.log('Exiting...');
46
- * process.exit(0);
47
- * });
48
- *
49
- * // With options
50
- * useExitOnCtrlCD({
51
- * onExit: () => saveAndQuit(),
52
- * enableCtrlC: true,
53
- * enableCtrlD: false,
54
- * exitMessage: '👋 See you later!',
55
- * confirmBeforeExit: true,
56
- * });
57
- * ```
58
- */
59
- export declare function useExitOnCtrlCD(handler: ExitHandler | UseExitOnCtrlCDOptions): void;
60
- /**
61
- * Convenience hook for just Ctrl+C handling
62
- *
63
- * @param {ExitHandler} handler - Exit callback
64
- * @param {boolean} [enabled=true] - Whether the handler is active
65
- * @example
66
- * ```typescript
67
- * useExitOnCtrlC(() => {
68
- * console.log('Interrupted');
69
- * });
70
- * ```
71
- */
72
- export declare function useExitOnCtrlC(handler: ExitHandler, enabled?: boolean): void;
73
- /**
74
- * Convenience hook for just Ctrl+D handling
75
- *
76
- * @param {ExitHandler} handler - Exit callback
77
- * @param {boolean} [enabled=true] - Whether the handler is active
78
- * @example
79
- * ```typescript
80
- * useExitOnCtrlD(() => {
81
- * console.log('EOF received');
82
- * });
83
- * ```
84
- */
85
- export declare function useExitOnCtrlD(handler: ExitHandler, enabled?: boolean): void;
86
- export default useExitOnCtrlCD;
@@ -1,130 +0,0 @@
1
- /**
2
- * @fileoverview Exit handler hook for gizzi-code integration
3
- * @module hooks/useExitOnCtrlCD
4
- *
5
- * Provides a React hook for handling exit key combinations (Ctrl+C and Ctrl+D).
6
- * Commonly used for CLI applications to handle graceful shutdown or exit actions.
7
- */
8
- import { useCallback } from 'react';
9
- import { useKeybinding } from './useKeybinding';
10
- /**
11
- * Default confirmation message
12
- * @constant {string}
13
- */
14
- const DEFAULT_CONFIRM_MESSAGE = 'Are you sure you want to exit? (y/N): ';
15
- /**
16
- * Default exit message
17
- * @constant {string}
18
- */
19
- const DEFAULT_EXIT_MESSAGE = 'Goodbye!';
20
- /**
21
- * React hook for handling Ctrl+C and Ctrl+D exit combinations
22
- *
23
- * Registers keyboard shortcuts for common terminal exit commands and
24
- * executes the provided callback when triggered. Supports optional
25
- * confirmation before exit.
26
- *
27
- * @param {ExitHandler | UseExitOnCtrlCDOptions} handler - Exit callback or options object
28
- * @example
29
- * ```typescript
30
- * // Simple usage with callback
31
- * useExitOnCtrlCD(() => {
32
- * console.log('Exiting...');
33
- * process.exit(0);
34
- * });
35
- *
36
- * // With options
37
- * useExitOnCtrlCD({
38
- * onExit: () => saveAndQuit(),
39
- * enableCtrlC: true,
40
- * enableCtrlD: false,
41
- * exitMessage: '👋 See you later!',
42
- * confirmBeforeExit: true,
43
- * });
44
- * ```
45
- */
46
- export function useExitOnCtrlCD(handler) {
47
- // Normalize input to options object
48
- const options = typeof handler === 'function' ? { onExit: handler } : handler;
49
- const { onExit, enableCtrlC = true, enableCtrlD = true, enabled = true, exitMessage = DEFAULT_EXIT_MESSAGE, confirmBeforeExit = false, confirmMessage = DEFAULT_CONFIRM_MESSAGE, } = options;
50
- const handleExit = useCallback(async (event) => {
51
- // Handle confirmation if enabled
52
- if (confirmBeforeExit) {
53
- // Note: In a real CLI environment, you might use readline here
54
- // For browser/React environments, this is a simplified version
55
- const confirmed = typeof window !== 'undefined'
56
- ? window.confirm(confirmMessage)
57
- : true;
58
- if (!confirmed) {
59
- return;
60
- }
61
- }
62
- // Show exit message
63
- if (exitMessage && typeof console !== 'undefined') {
64
- console.log(exitMessage);
65
- }
66
- // Execute exit handler
67
- if (onExit) {
68
- try {
69
- const result = await onExit();
70
- // Return false from handler to prevent default exit behavior
71
- if (result === false && event) {
72
- event.preventDefault();
73
- }
74
- }
75
- catch (error) {
76
- console.error('Error during exit:', error);
77
- }
78
- }
79
- }, [onExit, confirmBeforeExit, confirmMessage, exitMessage]);
80
- // Wrap handler to match KeyHandler signature
81
- const keyHandler = useCallback((event) => {
82
- handleExit(event);
83
- }, [handleExit]);
84
- // Register Ctrl+C handler (SIGINT equivalent)
85
- useKeybinding({ key: 'c', ctrl: true, preventDefault: true }, keyHandler, enabled && enableCtrlC);
86
- // Register Ctrl+D handler (EOF/exit equivalent)
87
- useKeybinding({ key: 'd', ctrl: true, preventDefault: true }, keyHandler, enabled && enableCtrlD);
88
- }
89
- /**
90
- * Convenience hook for just Ctrl+C handling
91
- *
92
- * @param {ExitHandler} handler - Exit callback
93
- * @param {boolean} [enabled=true] - Whether the handler is active
94
- * @example
95
- * ```typescript
96
- * useExitOnCtrlC(() => {
97
- * console.log('Interrupted');
98
- * });
99
- * ```
100
- */
101
- export function useExitOnCtrlC(handler, enabled = true) {
102
- useExitOnCtrlCD({
103
- onExit: handler,
104
- enableCtrlC: true,
105
- enableCtrlD: false,
106
- enabled,
107
- });
108
- }
109
- /**
110
- * Convenience hook for just Ctrl+D handling
111
- *
112
- * @param {ExitHandler} handler - Exit callback
113
- * @param {boolean} [enabled=true] - Whether the handler is active
114
- * @example
115
- * ```typescript
116
- * useExitOnCtrlD(() => {
117
- * console.log('EOF received');
118
- * });
119
- * ```
120
- */
121
- export function useExitOnCtrlD(handler, enabled = true) {
122
- useExitOnCtrlCD({
123
- onExit: handler,
124
- enableCtrlC: false,
125
- enableCtrlD: true,
126
- enabled,
127
- });
128
- }
129
- // Default export
130
- export default useExitOnCtrlCD;
@@ -1,89 +0,0 @@
1
- /**
2
- * @fileoverview Keybinding hook for gizzi-code integration
3
- * @module hooks/useKeybinding
4
- *
5
- * Provides a React hook for registering keyboard shortcuts and key combinations.
6
- * Supports modifier keys (Ctrl, Alt, Shift, Meta) and automatic cleanup on unmount.
7
- */
8
- /**
9
- * Key combination configuration
10
- * @interface KeybindingConfig
11
- */
12
- export interface KeybindingConfig {
13
- /** The main key (e.g., 'c', 'Enter', 'Escape') */
14
- readonly key: string;
15
- /** Require Ctrl key to be pressed */
16
- readonly ctrl?: boolean;
17
- /** Require Alt/Option key to be pressed */
18
- readonly alt?: boolean;
19
- /** Require Shift key to be pressed */
20
- readonly shift?: boolean;
21
- /** Require Meta/Command key to be pressed */
22
- readonly meta?: boolean;
23
- /** Prevent default browser behavior */
24
- readonly preventDefault?: boolean;
25
- /** Stop event propagation */
26
- readonly stopPropagation?: boolean;
27
- }
28
- /**
29
- * Parses a keybinding string into a config object
30
- *
31
- * @param {string} keybinding - Keybinding string (e.g., "Ctrl+C", "Escape", "Ctrl+Shift+A")
32
- * @returns {KeybindingConfig} Parsed keybinding configuration
33
- * @example
34
- * ```typescript
35
- * parseKeybinding("Ctrl+C"); // { key: 'c', ctrl: true }
36
- * parseKeybinding("Escape"); // { key: 'escape' }
37
- * parseKeybinding("Ctrl+Shift+A"); // { key: 'a', ctrl: true, shift: true }
38
- * ```
39
- */
40
- export declare function parseKeybinding(keybinding: string): KeybindingConfig;
41
- /**
42
- * Key event handler type
43
- * @typedef {Function} KeyHandler
44
- */
45
- export type KeyHandler = (event: KeyboardEvent) => void | boolean;
46
- /**
47
- * React hook for registering keyboard shortcuts
48
- *
49
- * Registers a keyboard shortcut that triggers the provided handler when pressed.
50
- * Automatically cleans up the event listener when the component unmounts or
51
- * when the keybinding changes.
52
- *
53
- * @param {string | KeybindingConfig} key - Key combination (e.g., "Ctrl+C") or config object
54
- * @param {KeyHandler} handler - Function to call when keybinding is triggered
55
- * @param {boolean} [enabled=true] - Whether the keybinding is active
56
- * @example
57
- * ```typescript
58
- * // Using string keybinding
59
- * useKeybinding('Ctrl+C', () => {
60
- * console.log('Copy!');
61
- * });
62
- *
63
- * // Using config object
64
- * useKeybinding({ key: 'k', ctrl: true }, (e) => {
65
- * e.preventDefault();
66
- * console.log('Ctrl+K pressed');
67
- * });
68
- *
69
- * // With conditional enabling
70
- * useKeybinding('Escape', handleClose, isModalOpen);
71
- * ```
72
- */
73
- export declare function useKeybinding(key: string | KeybindingConfig, handler: KeyHandler, enabled?: boolean): void;
74
- /**
75
- * Hook for registering multiple keybindings at once
76
- *
77
- * @param {Array<[string | KeybindingConfig, KeyHandler]>} bindings - Array of [keybinding, handler] tuples
78
- * @param {boolean} [enabled=true] - Whether all keybindings are active
79
- * @example
80
- * ```typescript
81
- * useKeybindings([
82
- * ['Ctrl+C', handleCopy],
83
- * ['Ctrl+V', handlePaste],
84
- * ['Escape', handleClose],
85
- * ]);
86
- * ```
87
- */
88
- export declare function useKeybindings(bindings: Array<[string | KeybindingConfig, KeyHandler]>, enabled?: boolean): void;
89
- export default useKeybinding;