@allternit/gizzi-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/WORKSPACE_INTEGRATION.md +290 -0
- package/chat-sessions/sessions-index.json +98 -0
- package/package.json +43 -0
- package/package.json.original +31 -0
- package/package.json.publish +47 -0
- package/src/bootstrap/state.d.ts +169 -0
- package/src/bootstrap/state.js +261 -0
- package/src/bootstrap/state.ts +371 -0
- package/src/context/pack-builder.d.ts +24 -0
- package/src/context/pack-builder.js +281 -0
- package/src/context/pack-builder.ts +334 -0
- package/src/hooks/useExitOnCtrlCD.d.ts +86 -0
- package/src/hooks/useExitOnCtrlCD.js +130 -0
- package/src/hooks/useExitOnCtrlCD.ts +202 -0
- package/src/hooks/useKeybinding.d.ts +89 -0
- package/src/hooks/useKeybinding.js +163 -0
- package/src/hooks/useKeybinding.ts +226 -0
- package/src/hooks/useTerminalSize.d.ts +41 -0
- package/src/hooks/useTerminalSize.js +90 -0
- package/src/hooks/useTerminalSize.ts +117 -0
- package/src/index.d.ts +23 -0
- package/src/index.js +24 -0
- package/src/index.ts +132 -0
- package/src/runtime/brand/brand.d.ts +488 -0
- package/src/runtime/brand/brand.js +464 -0
- package/src/runtime/brand/brand.ts +667 -0
- package/src/runtime/services/tokenEstimation.d.ts +187 -0
- package/src/runtime/services/tokenEstimation.js +423 -0
- package/src/runtime/services/tokenEstimation.ts +547 -0
- package/src/runtime/tools/Tool.d.ts +239 -0
- package/src/runtime/tools/Tool.js +285 -0
- package/src/runtime/tools/Tool.ts +524 -0
- package/src/scheduler/TaskScheduler.d.ts +98 -0
- package/src/scheduler/TaskScheduler.js +201 -0
- package/src/scheduler/TaskScheduler.ts +259 -0
- package/src/state/AppStateStore.d.ts +347 -0
- package/src/state/AppStateStore.js +439 -0
- package/src/state/AppStateStore.ts +658 -0
- package/src/state/WorkspaceStateStore.d.ts +43 -0
- package/src/state/WorkspaceStateStore.js +224 -0
- package/src/state/WorkspaceStateStore.ts +297 -0
- package/src/types/message.d.ts +190 -0
- package/src/types/message.js +77 -0
- package/src/types/message.ts +277 -0
- package/src/utils/format.d.ts +126 -0
- package/src/utils/format.js +230 -0
- package/src/utils/format.ts +336 -0
- package/src/utils/fullscreen.d.ts +161 -0
- package/src/utils/fullscreen.js +277 -0
- package/src/utils/fullscreen.ts +382 -0
- package/src/utils/sessionStorage.d.ts +210 -0
- package/src/utils/sessionStorage.js +435 -0
- package/src/utils/sessionStorage.ts +559 -0
- package/src/watcher/WorkspaceWatcher.d.ts +70 -0
- package/src/watcher/WorkspaceWatcher.js +191 -0
- package/src/watcher/WorkspaceWatcher.ts +251 -0
- package/src/workspace/loader.d.ts +30 -0
- package/src/workspace/loader.js +117 -0
- package/src/workspace/loader.ts +171 -0
- package/src/workspace/types.d.ts +91 -0
- package/src/workspace/types.js +7 -0
- package/src/workspace/types.ts +122 -0
- package/threads/thread_1775361175022.json +9 -0
- package/tsconfig.json +14 -0
|
@@ -0,0 +1,281 @@
|
|
|
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
|
+
}
|
|
@@ -0,0 +1,334 @@
|
|
|
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
|
+
import type {
|
|
9
|
+
ContextPack,
|
|
10
|
+
TrustTier,
|
|
11
|
+
ScheduledTask,
|
|
12
|
+
ToolDefinition,
|
|
13
|
+
WorkspaceFile
|
|
14
|
+
} from '../workspace/types';
|
|
15
|
+
|
|
16
|
+
// ============================================================================
|
|
17
|
+
// File Classification
|
|
18
|
+
// ============================================================================
|
|
19
|
+
|
|
20
|
+
export function classifyFile(filePath: string): WorkspaceFile['type'] {
|
|
21
|
+
const lower = filePath.toLowerCase();
|
|
22
|
+
|
|
23
|
+
if (lower.endsWith('manifest.json')) return 'manifest';
|
|
24
|
+
if (lower.includes('/brain/')) return 'brain';
|
|
25
|
+
if (lower.includes('/memory/')) return 'memory';
|
|
26
|
+
if (lower.endsWith('soul.md')) return 'soul';
|
|
27
|
+
if (lower.includes('/identity/identity.md')) return 'identity';
|
|
28
|
+
if (lower.includes('/identity/user.md')) return 'user';
|
|
29
|
+
if (lower.includes('/identity/voice.md')) return 'voice';
|
|
30
|
+
if (lower.includes('/identity/policy.md')) return 'policy';
|
|
31
|
+
if (lower.includes('/governance/playbook.md')) return 'playbook';
|
|
32
|
+
if (lower.includes('/governance/tools.md')) return 'tools';
|
|
33
|
+
if (lower.includes('/governance/heartbeat.md')) return 'heartbeat';
|
|
34
|
+
if (lower.includes('/governance/system.md')) return 'system';
|
|
35
|
+
if (lower.includes('/governance/channels.md')) return 'channels';
|
|
36
|
+
if (lower.includes('/skills/')) return 'skill';
|
|
37
|
+
if (lower.includes('/business/')) return 'business';
|
|
38
|
+
if (lower.endsWith('.json') || lower.endsWith('.yaml') || lower.endsWith('.yml')) return 'config';
|
|
39
|
+
|
|
40
|
+
return 'knowledge';
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// ============================================================================
|
|
44
|
+
// SOUL.md Parser
|
|
45
|
+
// ============================================================================
|
|
46
|
+
|
|
47
|
+
export function parseSoulMd(content: string): {
|
|
48
|
+
trustTiers: ContextPack['trustTiers'];
|
|
49
|
+
identity: Partial<ContextPack['identity']>
|
|
50
|
+
} {
|
|
51
|
+
const lines = content.split('\n');
|
|
52
|
+
|
|
53
|
+
const trustTiers: ContextPack['trustTiers'] = {
|
|
54
|
+
tier1: { level: 1, name: 'Foundation', rules: [], enforce: 'always' },
|
|
55
|
+
tier2: { level: 2, name: 'Contextual', rules: [], enforce: 'contextual' },
|
|
56
|
+
tier3: { level: 3, name: 'Permission Required', rules: [], enforce: 'permission' },
|
|
57
|
+
};
|
|
58
|
+
|
|
59
|
+
const identity: Partial<ContextPack['identity']> = {
|
|
60
|
+
personalityTraits: [],
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
let currentTier: 1 | 2 | 3 | null = null;
|
|
64
|
+
let inSelfAwareness = false;
|
|
65
|
+
|
|
66
|
+
for (const line of lines) {
|
|
67
|
+
const trimmed = line.trim();
|
|
68
|
+
|
|
69
|
+
if (trimmed.match(/^#+\s*Tier\s*1/i)) {
|
|
70
|
+
currentTier = 1;
|
|
71
|
+
} else if (trimmed.match(/^#+\s*Tier\s*2/i)) {
|
|
72
|
+
currentTier = 2;
|
|
73
|
+
} else if (trimmed.match(/^#+\s*Tier\s*3/i)) {
|
|
74
|
+
currentTier = 3;
|
|
75
|
+
} else if (trimmed.match(/^#+\s*Self-Awareness/i)) {
|
|
76
|
+
inSelfAwareness = true;
|
|
77
|
+
currentTier = null;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (currentTier && trimmed.match(/^[-\*✅]\s+/)) {
|
|
81
|
+
const rule = trimmed.replace(/^[-\*✅]\s+/, '');
|
|
82
|
+
trustTiers[`tier${currentTier}`].rules.push(rule);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
if (inSelfAwareness && trimmed.startsWith('I am')) {
|
|
86
|
+
identity.backstory = trimmed;
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return { trustTiers, identity };
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
// ============================================================================
|
|
94
|
+
// HEARTBEAT.md Parser
|
|
95
|
+
// ============================================================================
|
|
96
|
+
|
|
97
|
+
export function parseHeartbeatMd(content: string): ScheduledTask[] {
|
|
98
|
+
const lines = content.split('\n');
|
|
99
|
+
const tasks: ScheduledTask[] = [];
|
|
100
|
+
|
|
101
|
+
let currentFrequency: ScheduledTask['frequency'] = 'daily';
|
|
102
|
+
|
|
103
|
+
for (const line of lines) {
|
|
104
|
+
const trimmed = line.trim();
|
|
105
|
+
|
|
106
|
+
if (trimmed.match(/^#+\s*Daily/i)) {
|
|
107
|
+
currentFrequency = 'daily';
|
|
108
|
+
} else if (trimmed.match(/^#+\s*Weekly/i)) {
|
|
109
|
+
currentFrequency = 'weekly';
|
|
110
|
+
} else if (trimmed.match(/^#+\s*Monthly/i)) {
|
|
111
|
+
currentFrequency = 'monthly';
|
|
112
|
+
} else if (trimmed.match(/^#+\s*On\s+Session\s+Start/i)) {
|
|
113
|
+
currentFrequency = 'on-session-start';
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
const taskMatch = trimmed.match(/^-\s*\[([ xX])\]\s*(.+)/);
|
|
117
|
+
if (taskMatch) {
|
|
118
|
+
tasks.push({
|
|
119
|
+
id: `task-${Date.now()}-${tasks.length}`,
|
|
120
|
+
frequency: currentFrequency,
|
|
121
|
+
action: taskMatch[2].trim(),
|
|
122
|
+
lastExecuted: taskMatch[1].toLowerCase() === 'x' ? new Date().toISOString() : undefined,
|
|
123
|
+
});
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
return tasks;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// ============================================================================
|
|
131
|
+
// System Prompt Builder
|
|
132
|
+
// ============================================================================
|
|
133
|
+
|
|
134
|
+
export function buildSystemPrompt(pack: ContextPack): string {
|
|
135
|
+
const sections: string[] = [];
|
|
136
|
+
|
|
137
|
+
// Identity
|
|
138
|
+
sections.push(`# Agent Identity
|
|
139
|
+
|
|
140
|
+
You are ${pack.identity.name}.
|
|
141
|
+
|
|
142
|
+
## Purpose
|
|
143
|
+
${pack.identity.purpose}
|
|
144
|
+
|
|
145
|
+
## Backstory
|
|
146
|
+
${pack.identity.backstory}
|
|
147
|
+
|
|
148
|
+
## Personality Traits
|
|
149
|
+
${pack.identity.personalityTraits.map(t => `- ${t}`).join('\n')}`);
|
|
150
|
+
|
|
151
|
+
// Trust Tiers (CRITICAL)
|
|
152
|
+
sections.push(`# Trust & Safety (MUST FOLLOW)
|
|
153
|
+
|
|
154
|
+
## Tier 1 - Foundation (ALWAYS APPLY)
|
|
155
|
+
${pack.trustTiers.tier1.rules.map(r => `- ${r}`).join('\n')}
|
|
156
|
+
|
|
157
|
+
## Tier 2 - Contextual (APPLY WHEN RELEVANT)
|
|
158
|
+
${pack.trustTiers.tier2.rules.map(r => `- ${r}`).join('\n')}
|
|
159
|
+
|
|
160
|
+
## Tier 3 - Permission Required (ASK USER FIRST)
|
|
161
|
+
${pack.trustTiers.tier3.rules.map(r => `- ${r}`).join('\n')}
|
|
162
|
+
|
|
163
|
+
### BEFORE ANY ACTION:
|
|
164
|
+
1. Check if action violates Tier 1 → NEVER DO
|
|
165
|
+
2. Check if action matches Tier 2 → APPLY IF CONTEXT FITS
|
|
166
|
+
3. Check if action requires Tier 3 → ASK USER PERMISSION`);
|
|
167
|
+
|
|
168
|
+
// Governance
|
|
169
|
+
if (pack.governance.playbook) {
|
|
170
|
+
sections.push(`# Governance & Procedures
|
|
171
|
+
|
|
172
|
+
${pack.governance.playbook}`);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
// Tools
|
|
176
|
+
if (pack.governance.availableTools.length > 0) {
|
|
177
|
+
sections.push(`# Available Tools
|
|
178
|
+
|
|
179
|
+
${pack.governance.availableTools.map(t => `- **${t.name}**: ${t.description}${t.requiresPermission ? ' (Requires Permission)' : ''}`).join('\n')}`);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Hard Bans
|
|
183
|
+
if (pack.governance.hardBans.length > 0) {
|
|
184
|
+
sections.push(`# Hard Bans (NEVER DO THESE)
|
|
185
|
+
|
|
186
|
+
${pack.governance.hardBans.map(b => `- ❌ ${b}`).join('\n')}`);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
// Voice
|
|
190
|
+
sections.push(`# Voice & Communication Style
|
|
191
|
+
|
|
192
|
+
${pack.voice.style}
|
|
193
|
+
|
|
194
|
+
## Communication Rules
|
|
195
|
+
${pack.voice.rules.map(r => `- ${r}`).join('\n')}`);
|
|
196
|
+
|
|
197
|
+
// Memory
|
|
198
|
+
if (pack.memory.brain || pack.memory.activeTasks.length > 0) {
|
|
199
|
+
sections.push(`# Current Context
|
|
200
|
+
|
|
201
|
+
## Active Tasks
|
|
202
|
+
${pack.memory.activeTasks.map(t => `- ${t}`).join('\n') || 'None'}
|
|
203
|
+
|
|
204
|
+
## Key Lessons
|
|
205
|
+
${pack.memory.lessons.map(l => `- ${l}`).join('\n') || 'None'}`);
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
return sections.join('\n\n---\n\n');
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
// ============================================================================
|
|
212
|
+
// Context Pack Builder
|
|
213
|
+
// ============================================================================
|
|
214
|
+
|
|
215
|
+
export interface BuildContextPackOptions {
|
|
216
|
+
sessionId: string;
|
|
217
|
+
agentId: string;
|
|
218
|
+
agentName: string;
|
|
219
|
+
files: Map<string, string>; // path -> content
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export function buildContextPack(options: BuildContextPackOptions): ContextPack {
|
|
223
|
+
const { sessionId, agentId, agentName, files } = options;
|
|
224
|
+
|
|
225
|
+
// Parse files
|
|
226
|
+
const soulContent = files.has('.allternit/identity/SOUL.md')
|
|
227
|
+
? parseSoulMd(files.get('.allternit/identity/SOUL.md')!)
|
|
228
|
+
: {
|
|
229
|
+
trustTiers: {
|
|
230
|
+
tier1: { level: 1, name: 'Foundation', rules: ['Be helpful and accurate'], enforce: 'always' },
|
|
231
|
+
tier2: { level: 2, name: 'Contextual', rules: ['Adapt to context'], enforce: 'contextual' },
|
|
232
|
+
tier3: { level: 3, name: 'Permission Required', rules: ['Execute code'], enforce: 'permission' },
|
|
233
|
+
} as ContextPack['trustTiers'],
|
|
234
|
+
identity: { personalityTraits: ['helpful', 'accurate'] }
|
|
235
|
+
};
|
|
236
|
+
|
|
237
|
+
const heartbeatContent = files.has('.allternit/governance/HEARTBEAT.md')
|
|
238
|
+
? parseHeartbeatMd(files.get('.allternit/governance/HEARTBEAT.md')!)
|
|
239
|
+
: [];
|
|
240
|
+
|
|
241
|
+
// Build pack
|
|
242
|
+
const pack: ContextPack = {
|
|
243
|
+
version: '1.0.0',
|
|
244
|
+
agentId,
|
|
245
|
+
agentName,
|
|
246
|
+
sessionId,
|
|
247
|
+
|
|
248
|
+
identity: {
|
|
249
|
+
name: agentName,
|
|
250
|
+
purpose: files.get('.allternit/identity/IDENTITY.md')?.match(/##?\s*Purpose\s*\n([^#]+)/)?.[1]?.trim() || 'Assist the user',
|
|
251
|
+
backstory: soulContent.identity.backstory || `I am ${agentName}, an AI assistant.`,
|
|
252
|
+
personalityTraits: soulContent.identity.personalityTraits || ['helpful', 'accurate'],
|
|
253
|
+
},
|
|
254
|
+
|
|
255
|
+
trustTiers: soulContent.trustTiers,
|
|
256
|
+
|
|
257
|
+
governance: {
|
|
258
|
+
playbook: files.get('.allternit/governance/PLAYBOOK.md') || '',
|
|
259
|
+
availableTools: [], // Would parse from TOOLS.md
|
|
260
|
+
hardBans: [],
|
|
261
|
+
escalation: [],
|
|
262
|
+
},
|
|
263
|
+
|
|
264
|
+
heartbeat: {
|
|
265
|
+
tasks: heartbeatContent,
|
|
266
|
+
lastCheck: new Date().toISOString(),
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
memory: {
|
|
270
|
+
brain: files.get('.allternit/brain/BRAIN.md') || '',
|
|
271
|
+
activeTasks: [],
|
|
272
|
+
lessons: [],
|
|
273
|
+
userPreferences: {},
|
|
274
|
+
},
|
|
275
|
+
|
|
276
|
+
voice: {
|
|
277
|
+
style: files.get('.allternit/identity/VOICE.md') || 'professional and helpful',
|
|
278
|
+
tone: { formality: 0.5, enthusiasm: 0.5, empathy: 0.5, directness: 0.5 },
|
|
279
|
+
rules: [],
|
|
280
|
+
},
|
|
281
|
+
|
|
282
|
+
systemPrompt: '',
|
|
283
|
+
hash: '',
|
|
284
|
+
createdAt: new Date().toISOString(),
|
|
285
|
+
expiresAt: new Date(Date.now() + 5 * 60 * 1000).toISOString(),
|
|
286
|
+
};
|
|
287
|
+
|
|
288
|
+
// Build system prompt
|
|
289
|
+
pack.systemPrompt = buildSystemPrompt(pack);
|
|
290
|
+
|
|
291
|
+
// Generate hash
|
|
292
|
+
pack.hash = generateHash(pack);
|
|
293
|
+
|
|
294
|
+
return pack;
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
function generateHash(pack: Partial<ContextPack>): string {
|
|
298
|
+
const str = JSON.stringify({
|
|
299
|
+
agentId: pack.agentId,
|
|
300
|
+
trustTiers: pack.trustTiers,
|
|
301
|
+
systemPrompt: pack.systemPrompt?.slice(0, 100),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
let hash = 0;
|
|
305
|
+
for (let i = 0; i < str.length; i++) {
|
|
306
|
+
const char = str.charCodeAt(i);
|
|
307
|
+
hash = ((hash << 5) - hash) + char;
|
|
308
|
+
hash = hash & hash;
|
|
309
|
+
}
|
|
310
|
+
return Math.abs(hash).toString(16).padStart(16, '0');
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
// ============================================================================
|
|
314
|
+
// Utility Functions
|
|
315
|
+
// ============================================================================
|
|
316
|
+
|
|
317
|
+
export function getStartupTasks(pack: ContextPack): ScheduledTask[] {
|
|
318
|
+
return pack.heartbeat.tasks.filter(t => t.frequency === 'on-session-start');
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
export function requiresPermission(pack: ContextPack, action: string): boolean {
|
|
322
|
+
const actionLower = action.toLowerCase();
|
|
323
|
+
|
|
324
|
+
// Check Tier 3
|
|
325
|
+
if (pack.trustTiers.tier3.rules.some(r => actionLower.includes(r.toLowerCase()))) {
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
return false;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
export function shouldRefreshContext(pack: ContextPack): boolean {
|
|
333
|
+
return new Date() > new Date(pack.expiresAt);
|
|
334
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
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;
|