@cpretzinger/boss-claude 1.0.0 ā 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +304 -1
- package/bin/boss-claude.js +1138 -0
- package/bin/commands/mode.js +250 -0
- package/bin/onyx-guard.js +259 -0
- package/bin/onyx-guard.sh +251 -0
- package/bin/prompts.js +284 -0
- package/bin/rollback.js +85 -0
- package/bin/setup-wizard.js +492 -0
- package/config/.env.example +17 -0
- package/lib/README.md +83 -0
- package/lib/agent-logger.js +61 -0
- package/lib/agents/memory-engineers/github-memory-engineer.js +251 -0
- package/lib/agents/memory-engineers/postgres-memory-engineer.js +633 -0
- package/lib/agents/memory-engineers/qdrant-memory-engineer.js +358 -0
- package/lib/agents/memory-engineers/redis-memory-engineer.js +383 -0
- package/lib/agents/memory-supervisor.js +526 -0
- package/lib/agents/registry.js +135 -0
- package/lib/auto-monitor.js +131 -0
- package/lib/checkpoint-hook.js +112 -0
- package/lib/checkpoint.js +319 -0
- package/lib/commentator.js +213 -0
- package/lib/context-scribe.js +120 -0
- package/lib/delegation-strategies.js +326 -0
- package/lib/hierarchy-validator.js +643 -0
- package/lib/index.js +15 -0
- package/lib/init-with-mode.js +261 -0
- package/lib/init.js +44 -6
- package/lib/memory-result-aggregator.js +252 -0
- package/lib/memory.js +35 -7
- package/lib/mode-enforcer.js +473 -0
- package/lib/onyx-banner.js +169 -0
- package/lib/onyx-identity.js +214 -0
- package/lib/onyx-monitor.js +381 -0
- package/lib/onyx-reminder.js +188 -0
- package/lib/onyx-tool-interceptor.js +341 -0
- package/lib/onyx-wrapper.js +315 -0
- package/lib/orchestrator-gate.js +334 -0
- package/lib/output-formatter.js +296 -0
- package/lib/postgres.js +1 -1
- package/lib/prompt-injector.js +220 -0
- package/lib/prompts.js +532 -0
- package/lib/session.js +153 -6
- package/lib/setup/README.md +187 -0
- package/lib/setup/env-manager.js +785 -0
- package/lib/setup/error-recovery.js +630 -0
- package/lib/setup/explain-scopes.js +385 -0
- package/lib/setup/github-instructions.js +333 -0
- package/lib/setup/github-repo.js +254 -0
- package/lib/setup/import-credentials.js +498 -0
- package/lib/setup/index.js +62 -0
- package/lib/setup/init-postgres.js +785 -0
- package/lib/setup/init-redis.js +456 -0
- package/lib/setup/integration-test.js +652 -0
- package/lib/setup/progress.js +357 -0
- package/lib/setup/rollback.js +670 -0
- package/lib/setup/rollback.test.js +452 -0
- package/lib/setup/setup-with-rollback.example.js +351 -0
- package/lib/setup/summary.js +400 -0
- package/lib/setup/test-github-setup.js +10 -0
- package/lib/setup/test-postgres-init.js +98 -0
- package/lib/setup/verify-setup.js +102 -0
- package/lib/task-agent-worker.js +235 -0
- package/lib/token-monitor.js +466 -0
- package/lib/tool-wrapper-integration.js +369 -0
- package/lib/tool-wrapper.js +387 -0
- package/lib/validators/README.md +497 -0
- package/lib/validators/config.js +583 -0
- package/lib/validators/config.test.js +175 -0
- package/lib/validators/github.js +310 -0
- package/lib/validators/github.test.js +61 -0
- package/lib/validators/index.js +15 -0
- package/lib/validators/postgres.js +525 -0
- package/package.json +98 -13
- package/scripts/benchmark-memory.js +433 -0
- package/scripts/check-secrets.sh +12 -0
- package/scripts/fetch-todos.mjs +148 -0
- package/scripts/graceful-shutdown.sh +156 -0
- package/scripts/install-onyx-hooks.js +373 -0
- package/scripts/install.js +119 -18
- package/scripts/redis-monitor.js +284 -0
- package/scripts/redis-setup.js +412 -0
- package/scripts/test-memory-retrieval.js +201 -0
- package/scripts/validate-exports.js +68 -0
- package/scripts/validate-package.js +120 -0
- package/scripts/verify-onyx-deployment.js +309 -0
- package/scripts/verify-redis-deployment.js +354 -0
- package/scripts/verify-redis-init.js +219 -0
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OUTPUT FORMATTER
|
|
3
|
+
*
|
|
4
|
+
* Centralized output formatting utilities to prevent message truncation
|
|
5
|
+
* and ensure consistent display across all agent responses.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Format text for terminal output without truncation
|
|
10
|
+
*
|
|
11
|
+
* @param {string} text - Text to format
|
|
12
|
+
* @param {Object} options - Formatting options
|
|
13
|
+
* @param {number} options.maxWidth - Maximum width (0 = terminal width, default: 0)
|
|
14
|
+
* @param {boolean} options.wordWrap - Enable word wrapping (default: true)
|
|
15
|
+
* @param {string} options.indent - Indentation string (default: '')
|
|
16
|
+
* @param {boolean} options.preserveNewlines - Keep existing line breaks (default: true)
|
|
17
|
+
* @returns {string} Formatted text
|
|
18
|
+
*/
|
|
19
|
+
export function formatText(text, options = {}) {
|
|
20
|
+
const {
|
|
21
|
+
maxWidth = 0,
|
|
22
|
+
wordWrap = true,
|
|
23
|
+
indent = '',
|
|
24
|
+
preserveNewlines = true
|
|
25
|
+
} = options;
|
|
26
|
+
|
|
27
|
+
if (!text) return '';
|
|
28
|
+
|
|
29
|
+
// Calculate effective max width
|
|
30
|
+
const effectiveMaxWidth = maxWidth === 0 ? getTerminalWidth() - indent.length : maxWidth;
|
|
31
|
+
|
|
32
|
+
// If word wrap disabled, return as-is
|
|
33
|
+
if (!wordWrap) {
|
|
34
|
+
return text;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Word wrap implementation
|
|
38
|
+
const lines = preserveNewlines ? text.split('\n') : [text];
|
|
39
|
+
const wrappedLines = [];
|
|
40
|
+
|
|
41
|
+
for (const line of lines) {
|
|
42
|
+
if (line.length <= effectiveMaxWidth) {
|
|
43
|
+
wrappedLines.push(indent + line);
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// Split long lines at word boundaries
|
|
48
|
+
const words = line.split(/(\s+)/); // Preserve whitespace
|
|
49
|
+
let currentLine = '';
|
|
50
|
+
|
|
51
|
+
for (const word of words) {
|
|
52
|
+
const testLine = currentLine + word;
|
|
53
|
+
|
|
54
|
+
if (testLine.length <= effectiveMaxWidth) {
|
|
55
|
+
currentLine = testLine;
|
|
56
|
+
} else {
|
|
57
|
+
// If a single word is longer than max width, split it
|
|
58
|
+
if (currentLine.trim() === '' && word.trim().length > effectiveMaxWidth) {
|
|
59
|
+
// Hard wrap long words
|
|
60
|
+
for (let i = 0; i < word.length; i += effectiveMaxWidth) {
|
|
61
|
+
wrappedLines.push(indent + word.substring(i, i + effectiveMaxWidth));
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
if (currentLine.trim()) {
|
|
65
|
+
wrappedLines.push(indent + currentLine.trimEnd());
|
|
66
|
+
}
|
|
67
|
+
currentLine = word.trimStart();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
if (currentLine.trim()) {
|
|
73
|
+
wrappedLines.push(indent + currentLine.trimEnd());
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
return wrappedLines.join('\n');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Format agent response for display
|
|
82
|
+
* NEVER truncates content - shows full response with intelligent wrapping
|
|
83
|
+
*
|
|
84
|
+
* @param {string} response - Agent response text
|
|
85
|
+
* @param {Object} options - Formatting options
|
|
86
|
+
* @param {string} options.prefix - Prefix for response (default: '')
|
|
87
|
+
* @param {boolean} options.wordWrap - Enable word wrapping (default: true)
|
|
88
|
+
* @param {number} options.maxWidth - Maximum width (0 = terminal width, default: 0)
|
|
89
|
+
* @param {string} options.indent - Indentation for wrapped lines (default: ' ')
|
|
90
|
+
* @returns {string} Formatted response
|
|
91
|
+
*/
|
|
92
|
+
export function formatAgentResponse(response, options = {}) {
|
|
93
|
+
const {
|
|
94
|
+
prefix = '',
|
|
95
|
+
wordWrap = true,
|
|
96
|
+
maxWidth = 0,
|
|
97
|
+
indent = ' '
|
|
98
|
+
} = options;
|
|
99
|
+
|
|
100
|
+
if (!response) return '';
|
|
101
|
+
|
|
102
|
+
const effectiveMaxWidth = maxWidth === 0 ? getTerminalWidth() - 4 : maxWidth; // Leave margin
|
|
103
|
+
const formattedText = formatText(response, {
|
|
104
|
+
maxWidth: effectiveMaxWidth,
|
|
105
|
+
wordWrap,
|
|
106
|
+
indent,
|
|
107
|
+
preserveNewlines: true
|
|
108
|
+
});
|
|
109
|
+
|
|
110
|
+
return prefix ? `${prefix}\n${formattedText}` : formattedText;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Format task description for display
|
|
115
|
+
* NEVER truncates content - shows full task with intelligent wrapping
|
|
116
|
+
*
|
|
117
|
+
* @param {string} task - Task description
|
|
118
|
+
* @param {Object} options - Formatting options
|
|
119
|
+
* @param {string} options.prefix - Prefix for task (default: '')
|
|
120
|
+
* @param {boolean} options.wordWrap - Enable word wrapping (default: true)
|
|
121
|
+
* @param {number} options.maxWidth - Maximum width (0 = terminal width, default: 0)
|
|
122
|
+
* @param {string} options.indent - Indentation for wrapped lines (default: ' ')
|
|
123
|
+
* @returns {string} Formatted task
|
|
124
|
+
*/
|
|
125
|
+
export function formatTaskDescription(task, options = {}) {
|
|
126
|
+
const {
|
|
127
|
+
prefix = '',
|
|
128
|
+
wordWrap = true,
|
|
129
|
+
maxWidth = 0,
|
|
130
|
+
indent = ' '
|
|
131
|
+
} = options;
|
|
132
|
+
|
|
133
|
+
if (!task) return '';
|
|
134
|
+
|
|
135
|
+
const effectiveMaxWidth = maxWidth === 0 ? getTerminalWidth() - 4 : maxWidth; // Leave margin
|
|
136
|
+
const formattedText = formatText(task, {
|
|
137
|
+
maxWidth: effectiveMaxWidth,
|
|
138
|
+
wordWrap,
|
|
139
|
+
indent,
|
|
140
|
+
preserveNewlines: true
|
|
141
|
+
});
|
|
142
|
+
|
|
143
|
+
return prefix ? `${prefix}\n${formattedText}` : formattedText;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* Format command output for display
|
|
148
|
+
* Shows full command unless explicitly limited
|
|
149
|
+
*
|
|
150
|
+
* @param {string} command - Command string
|
|
151
|
+
* @param {Object} options - Formatting options
|
|
152
|
+
* @param {number} options.maxLength - Max length before truncation (0 = no limit)
|
|
153
|
+
* @returns {string} Formatted command
|
|
154
|
+
*/
|
|
155
|
+
export function formatCommand(command, options = {}) {
|
|
156
|
+
const { maxLength = 0 } = options;
|
|
157
|
+
|
|
158
|
+
if (!command) return '';
|
|
159
|
+
|
|
160
|
+
// Only truncate if maxLength explicitly set and > 0
|
|
161
|
+
if (maxLength > 0 && command.length > maxLength) {
|
|
162
|
+
return command.substring(0, maxLength) + '...';
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
return command;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
/**
|
|
169
|
+
* Format file path for display
|
|
170
|
+
* Optionally shows just filename or full path
|
|
171
|
+
*
|
|
172
|
+
* @param {string} filePath - File path
|
|
173
|
+
* @param {Object} options - Formatting options
|
|
174
|
+
* @param {boolean} options.basename - Show only filename (default: false)
|
|
175
|
+
* @returns {string} Formatted path
|
|
176
|
+
*/
|
|
177
|
+
export function formatFilePath(filePath, options = {}) {
|
|
178
|
+
const { basename = false } = options;
|
|
179
|
+
|
|
180
|
+
if (!filePath) return '[unknown]';
|
|
181
|
+
|
|
182
|
+
if (basename) {
|
|
183
|
+
return filePath.split('/').pop();
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
return filePath;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Get terminal width if available
|
|
191
|
+
* @returns {number} Terminal width in columns (default: 80)
|
|
192
|
+
*/
|
|
193
|
+
export function getTerminalWidth() {
|
|
194
|
+
return process.stdout.columns || 80;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/**
|
|
198
|
+
* Check if output is truncated
|
|
199
|
+
* @param {string} original - Original text
|
|
200
|
+
* @param {string} displayed - Displayed text
|
|
201
|
+
* @returns {boolean} True if truncated
|
|
202
|
+
*/
|
|
203
|
+
export function isTruncated(original, displayed) {
|
|
204
|
+
return original.length > displayed.length;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* Safe truncate with ellipsis
|
|
209
|
+
* Only use when truncation is explicitly needed
|
|
210
|
+
*
|
|
211
|
+
* @param {string} text - Text to truncate
|
|
212
|
+
* @param {number} maxLength - Maximum length (including ellipsis)
|
|
213
|
+
* @param {string} ellipsis - Ellipsis string (default: '...')
|
|
214
|
+
* @returns {string} Truncated text
|
|
215
|
+
*/
|
|
216
|
+
export function safeTruncate(text, maxLength, ellipsis = '...') {
|
|
217
|
+
if (!text || maxLength <= 0) return text;
|
|
218
|
+
if (text.length <= maxLength) return text;
|
|
219
|
+
|
|
220
|
+
const truncateAt = maxLength - ellipsis.length;
|
|
221
|
+
return text.substring(0, truncateAt) + ellipsis;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Format log details with intelligent line wrapping
|
|
226
|
+
* Used for watch command and live logging
|
|
227
|
+
*
|
|
228
|
+
* @param {string} details - Details text from log
|
|
229
|
+
* @param {Object} options - Formatting options
|
|
230
|
+
* @param {number} options.maxWidth - Maximum width for first line (0 = terminal width, default: 0)
|
|
231
|
+
* @param {string} options.continuationPrefix - Prefix for continuation lines (default: ' ')
|
|
232
|
+
* @param {boolean} options.multiline - Allow multiline output (default: true)
|
|
233
|
+
* @returns {string} Formatted details (may contain newlines)
|
|
234
|
+
*/
|
|
235
|
+
export function formatLogDetails(details, options = {}) {
|
|
236
|
+
const {
|
|
237
|
+
maxWidth = 0,
|
|
238
|
+
continuationPrefix = ' ',
|
|
239
|
+
multiline = true
|
|
240
|
+
} = options;
|
|
241
|
+
|
|
242
|
+
if (!details) return '';
|
|
243
|
+
|
|
244
|
+
const terminalWidth = getTerminalWidth();
|
|
245
|
+
const effectiveMaxWidth = maxWidth === 0 ? terminalWidth - 40 : maxWidth; // Leave room for timestamp/event/agent
|
|
246
|
+
|
|
247
|
+
// Single line mode - truncate if needed
|
|
248
|
+
if (!multiline) {
|
|
249
|
+
if (details.length <= effectiveMaxWidth) {
|
|
250
|
+
return details;
|
|
251
|
+
}
|
|
252
|
+
return safeTruncate(details, effectiveMaxWidth);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Multi-line mode - wrap intelligently
|
|
256
|
+
const lines = [];
|
|
257
|
+
let remainingText = details;
|
|
258
|
+
let isFirstLine = true;
|
|
259
|
+
|
|
260
|
+
while (remainingText.length > 0) {
|
|
261
|
+
const currentMaxWidth = isFirstLine ? effectiveMaxWidth : (terminalWidth - continuationPrefix.length - 4);
|
|
262
|
+
|
|
263
|
+
if (remainingText.length <= currentMaxWidth) {
|
|
264
|
+
lines.push(isFirstLine ? remainingText : continuationPrefix + remainingText);
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// Find last space before max width
|
|
269
|
+
let breakPoint = remainingText.lastIndexOf(' ', currentMaxWidth);
|
|
270
|
+
|
|
271
|
+
// If no space found, break at max width
|
|
272
|
+
if (breakPoint === -1 || breakPoint === 0) {
|
|
273
|
+
breakPoint = currentMaxWidth;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
const line = remainingText.substring(0, breakPoint).trimEnd();
|
|
277
|
+
lines.push(isFirstLine ? line : continuationPrefix + line);
|
|
278
|
+
|
|
279
|
+
remainingText = remainingText.substring(breakPoint).trimStart();
|
|
280
|
+
isFirstLine = false;
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
return lines.join('\n');
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
export default {
|
|
287
|
+
formatText,
|
|
288
|
+
formatAgentResponse,
|
|
289
|
+
formatTaskDescription,
|
|
290
|
+
formatCommand,
|
|
291
|
+
formatFilePath,
|
|
292
|
+
formatLogDetails,
|
|
293
|
+
getTerminalWidth,
|
|
294
|
+
isTruncated,
|
|
295
|
+
safeTruncate
|
|
296
|
+
};
|
package/lib/postgres.js
CHANGED
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SYSTEM PROMPT INJECTOR
|
|
3
|
+
*
|
|
4
|
+
* Automatically injects ONYX identity into system prompts and context refreshes.
|
|
5
|
+
* Ensures every interaction reinforces orchestrator-only behavior.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { getOnyxIdentityPrompt, getOnyxContextReminder, checkToolViolation } from './onyx-identity.js';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Intercepts and enhances system prompts with ONYX identity
|
|
13
|
+
*
|
|
14
|
+
* @param {string} originalPrompt - The original system prompt
|
|
15
|
+
* @param {Object} options - Injection options
|
|
16
|
+
* @returns {string} Enhanced prompt with ONYX identity injected
|
|
17
|
+
*/
|
|
18
|
+
export function injectOnyxIdentity(originalPrompt, options = {}) {
|
|
19
|
+
const {
|
|
20
|
+
position = 'prepend', // 'prepend', 'append', or 'both'
|
|
21
|
+
includeReminder = true,
|
|
22
|
+
emphasize = true
|
|
23
|
+
} = options;
|
|
24
|
+
|
|
25
|
+
const onyxIdentity = getOnyxIdentityPrompt();
|
|
26
|
+
const reminder = includeReminder ? getOnyxContextReminder() : '';
|
|
27
|
+
|
|
28
|
+
// Emphasize with visual separators
|
|
29
|
+
const emphasis = emphasize ? '\n\nā ļøā ļøā ļø CRITICAL IDENTITY CONTEXT ā ļøā ļøā ļø\n\n' : '';
|
|
30
|
+
|
|
31
|
+
switch (position) {
|
|
32
|
+
case 'prepend':
|
|
33
|
+
return `${emphasis}${onyxIdentity}\n\n${originalPrompt}`;
|
|
34
|
+
|
|
35
|
+
case 'append':
|
|
36
|
+
return `${originalPrompt}\n\n${emphasis}${onyxIdentity}`;
|
|
37
|
+
|
|
38
|
+
case 'both':
|
|
39
|
+
return `${emphasis}${onyxIdentity}\n\n${originalPrompt}\n\n${reminder}`;
|
|
40
|
+
|
|
41
|
+
default:
|
|
42
|
+
return `${emphasis}${onyxIdentity}\n\n${originalPrompt}`;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Creates a context refresh that reinforces ONYX identity
|
|
48
|
+
* Use this periodically in long conversations
|
|
49
|
+
*
|
|
50
|
+
* @param {Object} currentContext - Current conversation context
|
|
51
|
+
* @returns {string} Refresh prompt with ONYX identity
|
|
52
|
+
*/
|
|
53
|
+
export function createContextRefresh(currentContext = {}) {
|
|
54
|
+
const {
|
|
55
|
+
tasksSinceRefresh = 0,
|
|
56
|
+
delegationsSinceRefresh = 0,
|
|
57
|
+
violationsSinceRefresh = 0
|
|
58
|
+
} = currentContext;
|
|
59
|
+
|
|
60
|
+
const reminder = getOnyxContextReminder();
|
|
61
|
+
|
|
62
|
+
const stats = `
|
|
63
|
+
š SESSION METRICS (since last refresh):
|
|
64
|
+
⢠Tasks Analyzed: ${tasksSinceRefresh}
|
|
65
|
+
⢠Delegations Made: ${delegationsSinceRefresh}
|
|
66
|
+
⢠Violations Prevented: ${violationsSinceRefresh}
|
|
67
|
+
`;
|
|
68
|
+
|
|
69
|
+
return `${reminder}\n${stats}
|
|
70
|
+
|
|
71
|
+
Remember: Your power is in delegation, not execution.
|
|
72
|
+
The hierarchy exists for a reason - use it.
|
|
73
|
+
`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Hook for initialization - ensures ONYX identity is loaded first
|
|
78
|
+
*
|
|
79
|
+
* @param {Function} originalInit - The original initialization function
|
|
80
|
+
* @returns {Function} Wrapped initialization with ONYX injection
|
|
81
|
+
*/
|
|
82
|
+
export function wrapInitialization(originalInit) {
|
|
83
|
+
return async function onyxAwareInit(...args) {
|
|
84
|
+
// First, inject ONYX identity
|
|
85
|
+
console.log(chalk.blue('\nš· Loading ONYX Orchestrator Identity...\n'));
|
|
86
|
+
|
|
87
|
+
const onyxPrompt = getOnyxIdentityPrompt();
|
|
88
|
+
console.log(chalk.cyan(onyxPrompt));
|
|
89
|
+
|
|
90
|
+
// Then run original initialization
|
|
91
|
+
const result = await originalInit(...args);
|
|
92
|
+
|
|
93
|
+
// Enhance result with ONYX context
|
|
94
|
+
if (typeof result === 'string') {
|
|
95
|
+
return injectOnyxIdentity(result, { position: 'prepend', emphasize: true });
|
|
96
|
+
} else if (typeof result === 'object' && result.prompt) {
|
|
97
|
+
result.prompt = injectOnyxIdentity(result.prompt, { position: 'prepend', emphasize: true });
|
|
98
|
+
result.onyxMode = true;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return result;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Monitoring hook - intercepts tool usage to prevent worker tool violations
|
|
107
|
+
*
|
|
108
|
+
* @param {string} toolName - Tool being invoked
|
|
109
|
+
* @param {Object} toolParams - Tool parameters
|
|
110
|
+
* @returns {Object} Validation result with allowed status
|
|
111
|
+
*/
|
|
112
|
+
export function interceptToolUsage(toolName, toolParams = {}) {
|
|
113
|
+
const violation = checkToolViolation(toolName, toolParams);
|
|
114
|
+
|
|
115
|
+
if (violation.violation) {
|
|
116
|
+
console.log(chalk.red('\nšØ ONYX VIOLATION DETECTED šØ'));
|
|
117
|
+
console.log(chalk.red(`Tool: ${toolName}`));
|
|
118
|
+
console.log(chalk.red(`Severity: ${violation.severity}`));
|
|
119
|
+
console.log(chalk.yellow(`\n${violation.message}`));
|
|
120
|
+
console.log(chalk.cyan(`Action Required: ${violation.action}\n`));
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
allowed: false,
|
|
124
|
+
violation,
|
|
125
|
+
shouldDelegate: true
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (violation.warning) {
|
|
130
|
+
console.log(chalk.yellow(`\nā ļø Tool Usage Warning: ${violation.message}`));
|
|
131
|
+
console.log(chalk.dim(`Action: ${violation.action}\n`));
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
allowed: true,
|
|
136
|
+
violation: null,
|
|
137
|
+
shouldDelegate: false
|
|
138
|
+
};
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Automatic context refresh trigger
|
|
143
|
+
* Call this every N messages or tokens to re-inject ONYX identity
|
|
144
|
+
*
|
|
145
|
+
* @param {number} messageCount - Current message count
|
|
146
|
+
* @param {number} refreshInterval - Refresh every N messages (default: 10)
|
|
147
|
+
* @returns {string|null} Refresh prompt if needed, null otherwise
|
|
148
|
+
*/
|
|
149
|
+
export function autoRefreshContext(messageCount, refreshInterval = 10) {
|
|
150
|
+
if (messageCount > 0 && messageCount % refreshInterval === 0) {
|
|
151
|
+
console.log(chalk.blue(`\nš ONYX Context Refresh (Message ${messageCount})\n`));
|
|
152
|
+
return createContextRefresh();
|
|
153
|
+
}
|
|
154
|
+
return null;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
/**
|
|
158
|
+
* Pre-delegation hook - reinforces that delegation is ONYX's primary function
|
|
159
|
+
*
|
|
160
|
+
* @param {Object} delegationRequest - The delegation being made
|
|
161
|
+
* @returns {Object} Enhanced delegation with ONYX context
|
|
162
|
+
*/
|
|
163
|
+
export function enhanceDelegation(delegationRequest) {
|
|
164
|
+
const {
|
|
165
|
+
agent,
|
|
166
|
+
task,
|
|
167
|
+
priority,
|
|
168
|
+
deadline
|
|
169
|
+
} = delegationRequest;
|
|
170
|
+
|
|
171
|
+
// Add ONYX context to delegation
|
|
172
|
+
const enhanced = {
|
|
173
|
+
...delegationRequest,
|
|
174
|
+
delegatedBy: 'ONYX',
|
|
175
|
+
delegationType: 'orchestrator_to_specialist',
|
|
176
|
+
hierarchyLevel: 'meta_boss_to_worker',
|
|
177
|
+
onyxNote: `ONYX (Meta-Boss) has analyzed this task and determined ${agent} is the optimal specialist. This is proper hierarchy delegation.`
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
console.log(chalk.green(`\nā
ONYX DELEGATION`));
|
|
181
|
+
console.log(chalk.white(`Task: ${task}`));
|
|
182
|
+
console.log(chalk.cyan(`Delegating to: ${agent}`));
|
|
183
|
+
console.log(chalk.dim(`Type: ${enhanced.delegationType}\n`));
|
|
184
|
+
|
|
185
|
+
return enhanced;
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
/**
|
|
189
|
+
* Generate startup banner for ONYX mode
|
|
190
|
+
*
|
|
191
|
+
* @returns {string} ONYX startup banner
|
|
192
|
+
*/
|
|
193
|
+
export function getOnyxStartupBanner() {
|
|
194
|
+
return `
|
|
195
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
196
|
+
ā ā
|
|
197
|
+
ā āāāāāāāā āāāā āāā āāā āāā āāā āāā ā
|
|
198
|
+
ā āāāāāāāā āāāāā āāā āāāā āāāā āāāāāāāā ā
|
|
199
|
+
ā āāā āāā āāāāāā āāā āāāāāāā āāāāāā ā
|
|
200
|
+
ā āāā āāā āāāāāāāāāā āāāāā āāāāāā ā
|
|
201
|
+
ā āāāāāāāāā āāā āāāāāā āāā āāāā āāā ā
|
|
202
|
+
ā āāāāāāāā āāā āāāāā āāā āāā āāā ā
|
|
203
|
+
ā ā
|
|
204
|
+
ā META-BOSS ORCHESTRATOR ONLINE ā
|
|
205
|
+
ā ā
|
|
206
|
+
āāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāāā
|
|
207
|
+
|
|
208
|
+
Mode: ORCHESTRATOR ONLY
|
|
209
|
+
Delegation: MANDATORY
|
|
210
|
+
Direct Execution: FORBIDDEN
|
|
211
|
+
|
|
212
|
+
Your role: Analyze ā Delegate ā Validate
|
|
213
|
+
`;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
export {
|
|
217
|
+
getOnyxIdentityPrompt,
|
|
218
|
+
getOnyxContextReminder,
|
|
219
|
+
checkToolViolation
|
|
220
|
+
};
|