myshell-tools 1.0.0 → 2.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/CHANGELOG.md +44 -69
- package/LICENSE +21 -21
- package/README.md +178 -318
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cost.d.ts +36 -0
- package/dist/commands/cost.js +103 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/doctor.d.ts +36 -0
- package/dist/commands/doctor.js +115 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts +20 -0
- package/dist/commands/login.js +60 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/core/assess.d.ts +25 -0
- package/dist/core/assess.js +142 -0
- package/dist/core/assess.js.map +1 -0
- package/dist/core/classify.d.ts +19 -0
- package/dist/core/classify.js +80 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/escalate.d.ts +32 -0
- package/dist/core/escalate.js +57 -0
- package/dist/core/escalate.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/orchestrate.d.ts +42 -0
- package/dist/core/orchestrate.js +439 -0
- package/dist/core/orchestrate.js.map +1 -0
- package/dist/core/policy.d.ts +9 -0
- package/dist/core/policy.js +27 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/prompt.d.ts +26 -0
- package/dist/core/prompt.js +125 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/review.d.ts +46 -0
- package/dist/core/review.js +148 -0
- package/dist/core/review.js.map +1 -0
- package/dist/core/route.d.ts +28 -0
- package/dist/core/route.js +52 -0
- package/dist/core/route.js.map +1 -0
- package/dist/core/types.d.ts +141 -0
- package/dist/core/types.js +14 -0
- package/dist/core/types.js.map +1 -0
- package/dist/infra/atomic.d.ts +53 -0
- package/dist/infra/atomic.js +171 -0
- package/dist/infra/atomic.js.map +1 -0
- package/dist/infra/clock.d.ts +9 -0
- package/dist/infra/clock.js +15 -0
- package/dist/infra/clock.js.map +1 -0
- package/dist/infra/index.d.ts +9 -0
- package/dist/infra/index.js +7 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/ledger.d.ts +49 -0
- package/dist/infra/ledger.js +90 -0
- package/dist/infra/ledger.js.map +1 -0
- package/dist/infra/paths.d.ts +28 -0
- package/dist/infra/paths.js +38 -0
- package/dist/infra/paths.js.map +1 -0
- package/dist/infra/pricing.d.ts +47 -0
- package/dist/infra/pricing.js +151 -0
- package/dist/infra/pricing.js.map +1 -0
- package/dist/infra/session.d.ts +28 -0
- package/dist/infra/session.js +61 -0
- package/dist/infra/session.js.map +1 -0
- package/dist/interface/render.d.ts +27 -0
- package/dist/interface/render.js +134 -0
- package/dist/interface/render.js.map +1 -0
- package/dist/interface/repl.d.ts +23 -0
- package/dist/interface/repl.js +90 -0
- package/dist/interface/repl.js.map +1 -0
- package/dist/interface/run.d.ts +20 -0
- package/dist/interface/run.js +31 -0
- package/dist/interface/run.js.map +1 -0
- package/dist/providers/claude-parse.d.ts +24 -0
- package/dist/providers/claude-parse.js +113 -0
- package/dist/providers/claude-parse.js.map +1 -0
- package/dist/providers/claude.d.ts +45 -0
- package/dist/providers/claude.js +122 -0
- package/dist/providers/claude.js.map +1 -0
- package/dist/providers/codex-parse.d.ts +32 -0
- package/dist/providers/codex-parse.js +145 -0
- package/dist/providers/codex-parse.js.map +1 -0
- package/dist/providers/codex.d.ts +44 -0
- package/dist/providers/codex.js +124 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/detect.d.ts +49 -0
- package/dist/providers/detect.js +125 -0
- package/dist/providers/detect.js.map +1 -0
- package/dist/providers/errors.d.ts +49 -0
- package/dist/providers/errors.js +189 -0
- package/dist/providers/errors.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/port.d.ts +74 -0
- package/dist/providers/port.js +16 -0
- package/dist/providers/port.js.map +1 -0
- package/dist/providers/registry.d.ts +21 -0
- package/dist/providers/registry.js +34 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/ui/banner.d.ts +19 -0
- package/dist/ui/banner.js +32 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/spinner.d.ts +27 -0
- package/dist/ui/spinner.js +67 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/theme.d.ts +32 -0
- package/dist/ui/theme.js +56 -0
- package/dist/ui/theme.js.map +1 -0
- package/package.json +55 -49
- package/data/orchestrator.json +0 -113
- package/src/auth/recovery.mjs +0 -328
- package/src/auth/refresh.mjs +0 -373
- package/src/chef.mjs +0 -348
- package/src/cli/doctor.mjs +0 -568
- package/src/cli/reset.mjs +0 -447
- package/src/cli/status.mjs +0 -379
- package/src/cli.mjs +0 -429
- package/src/commands/doctor.mjs +0 -375
- package/src/commands/help.mjs +0 -324
- package/src/commands/status.mjs +0 -331
- package/src/monitor/health.mjs +0 -486
- package/src/monitor/performance.mjs +0 -442
- package/src/monitor/report.mjs +0 -535
- package/src/orchestrator/classify.mjs +0 -391
- package/src/orchestrator/confidence.mjs +0 -151
- package/src/orchestrator/handoffs.mjs +0 -231
- package/src/orchestrator/review.mjs +0 -222
- package/src/providers/balance.mjs +0 -201
- package/src/providers/claude.mjs +0 -236
- package/src/providers/codex.mjs +0 -255
- package/src/providers/detect.mjs +0 -185
- package/src/providers/errors.mjs +0 -373
- package/src/providers/select.mjs +0 -162
- package/src/repl-enhanced.mjs +0 -417
- package/src/repl.mjs +0 -321
- package/src/state/archive.mjs +0 -366
- package/src/state/atomic.mjs +0 -116
- package/src/state/cleanup.mjs +0 -440
- package/src/state/recovery.mjs +0 -461
- package/src/state/session.mjs +0 -147
- package/src/ui/errors.mjs +0 -456
- package/src/ui/formatter.mjs +0 -327
- package/src/ui/icons.mjs +0 -318
- package/src/ui/progress.mjs +0 -468
- package/templates/prompts/confidence-format.txt +0 -14
- package/templates/prompts/ic-with-feedback.txt +0 -41
- package/templates/prompts/ic.txt +0 -13
- package/templates/prompts/manager-review.txt +0 -40
- package/templates/prompts/manager.txt +0 -14
- package/templates/prompts/worker.txt +0 -12
|
@@ -1,391 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* classify.mjs — Simple task classification for hierarchical routing
|
|
3
|
-
* Adapted from archive/dual-brain/hooks/vibe-router.mjs
|
|
4
|
-
*/
|
|
5
|
-
|
|
6
|
-
/**
|
|
7
|
-
* Risk keyword patterns for escalation detection
|
|
8
|
-
*/
|
|
9
|
-
const RISK_KEYWORDS = [
|
|
10
|
-
{
|
|
11
|
-
level: 'critical',
|
|
12
|
-
regex: /\b(auth|credential|secret|\.env|key[s]?|token[s]?|password|encrypt|certificate)\b/i,
|
|
13
|
-
label: 'security-sensitive'
|
|
14
|
-
},
|
|
15
|
-
{
|
|
16
|
-
level: 'high',
|
|
17
|
-
regex: /\b(login|payment|billing|deploy|migration|ci[-/]?cd|permission|policy|schema|api[-_]?contract)\b/i,
|
|
18
|
-
label: 'high-impact'
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
level: 'medium',
|
|
22
|
-
regex: /\b(test|spec|config|integration|shared|util|lib)\b/i,
|
|
23
|
-
label: 'shared/tested code'
|
|
24
|
-
},
|
|
25
|
-
{
|
|
26
|
-
level: 'low',
|
|
27
|
-
regex: /\b(readme|docs?|comment|format|lint|style|typo|changelog|nav|ui|css|color|font|margin|padding)\b/i,
|
|
28
|
-
label: 'docs/UI'
|
|
29
|
-
}
|
|
30
|
-
];
|
|
31
|
-
|
|
32
|
-
const LEVEL_ORDER = { critical: 3, high: 2, medium: 1, low: 0 };
|
|
33
|
-
|
|
34
|
-
/**
|
|
35
|
-
* Tier detection patterns
|
|
36
|
-
*/
|
|
37
|
-
const WORKER_WORDS = /\b(explore|search|find|grep|locate|where\s+is|list\s+files|read[-\s]?only|lookup|scan|check|look|where|what)\b/i;
|
|
38
|
-
const MANAGER_WORDS = /\b(review|plan|design|architect|decide|analyze|audit|security|code[-\s]?review|threat[-\s]?model|complex[-\s]?debug|evaluate|compare|assess)\b/i;
|
|
39
|
-
|
|
40
|
-
/**
|
|
41
|
-
* Classify task risk level based on keywords
|
|
42
|
-
*/
|
|
43
|
-
function classifyKeywordRisk(text) {
|
|
44
|
-
let highest = { level: 'low', reason: 'general task' };
|
|
45
|
-
|
|
46
|
-
for (const pattern of RISK_KEYWORDS) {
|
|
47
|
-
const match = text.match(pattern.regex);
|
|
48
|
-
if (match && LEVEL_ORDER[pattern.level] > LEVEL_ORDER[highest.level]) {
|
|
49
|
-
highest = { level: pattern.level, reason: `${pattern.label} (${match[0]})` };
|
|
50
|
-
if (pattern.level === 'critical') return highest;
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return highest;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Detect file paths in text and classify their risk
|
|
59
|
-
*/
|
|
60
|
-
function extractPaths(text) {
|
|
61
|
-
const pathRegex = /(?:^|\s)([\w./\-_]+\/[\w./\-_]*\.[\w]+)(?:\s|$)/g;
|
|
62
|
-
const paths = [];
|
|
63
|
-
let match;
|
|
64
|
-
|
|
65
|
-
while ((match = pathRegex.exec(text)) !== null) {
|
|
66
|
-
paths.push(match[1]);
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
return paths;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function classifyPathRisk(paths) {
|
|
73
|
-
if (paths.length === 0) return { level: 'low', reason: 'no files mentioned' };
|
|
74
|
-
|
|
75
|
-
let highest = { level: 'low', reason: 'general files' };
|
|
76
|
-
|
|
77
|
-
for (const path of paths) {
|
|
78
|
-
const lowerPath = path.toLowerCase();
|
|
79
|
-
|
|
80
|
-
if (lowerPath.includes('.env') ||
|
|
81
|
-
lowerPath.includes('secret') ||
|
|
82
|
-
lowerPath.includes('credential')) {
|
|
83
|
-
return { level: 'critical', reason: `sensitive file (${path})` };
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
if (lowerPath.includes('auth') ||
|
|
87
|
-
lowerPath.includes('security') ||
|
|
88
|
-
lowerPath.includes('payment') ||
|
|
89
|
-
lowerPath.includes('billing')) {
|
|
90
|
-
highest = { level: 'high', reason: `sensitive directory (${path})` };
|
|
91
|
-
} else if (lowerPath.includes('test') ||
|
|
92
|
-
lowerPath.includes('spec') ||
|
|
93
|
-
lowerPath.includes('config')) {
|
|
94
|
-
if (LEVEL_ORDER['medium'] > LEVEL_ORDER[highest.level]) {
|
|
95
|
-
highest = { level: 'medium', reason: `shared/test file (${path})` };
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
return highest;
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
/**
|
|
104
|
-
* Determine the appropriate starting tier for a task
|
|
105
|
-
*/
|
|
106
|
-
function classifyTier(text) {
|
|
107
|
-
if (MANAGER_WORDS.test(text)) return 'manager';
|
|
108
|
-
if (WORKER_WORDS.test(text)) return 'worker';
|
|
109
|
-
return 'ic'; // Default to IC tier
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Enhanced multi-signal classification function
|
|
114
|
-
*/
|
|
115
|
-
export function classifyTask(userMsg, fileContext) {
|
|
116
|
-
const tier = classifyTier(userMsg);
|
|
117
|
-
|
|
118
|
-
// Extract signals for classification
|
|
119
|
-
const keywords = extractKeywords(userMsg);
|
|
120
|
-
const paths = extractMentionedFiles(userMsg, fileContext);
|
|
121
|
-
const complexity = assessComplexity(userMsg);
|
|
122
|
-
|
|
123
|
-
// Multi-signal risk assessment
|
|
124
|
-
const keywordRisk = classifyKeywordRisk(userMsg);
|
|
125
|
-
const fileRisk = classifyFileRisk(paths);
|
|
126
|
-
const complexityRisk = classifyComplexityRisk(complexity);
|
|
127
|
-
|
|
128
|
-
// Take the highest risk level
|
|
129
|
-
const risks = [keywordRisk, fileRisk, complexityRisk];
|
|
130
|
-
const highestRisk = risks.reduce((max, current) =>
|
|
131
|
-
LEVEL_ORDER[current.level] > LEVEL_ORDER[max.level] ? current : max
|
|
132
|
-
);
|
|
133
|
-
|
|
134
|
-
// Estimate confidence based on multiple signals
|
|
135
|
-
const confidence = estimateTaskConfidence(keywords, complexity, paths, tier);
|
|
136
|
-
|
|
137
|
-
return {
|
|
138
|
-
task: userMsg.trim(),
|
|
139
|
-
tier,
|
|
140
|
-
risk: highestRisk.level,
|
|
141
|
-
reason: highestRisk.reason,
|
|
142
|
-
paths,
|
|
143
|
-
keywords,
|
|
144
|
-
complexity,
|
|
145
|
-
confidence,
|
|
146
|
-
signals: {
|
|
147
|
-
keywordRisk,
|
|
148
|
-
fileRisk,
|
|
149
|
-
complexityRisk
|
|
150
|
-
}
|
|
151
|
-
};
|
|
152
|
-
}
|
|
153
|
-
|
|
154
|
-
/**
|
|
155
|
-
* Legacy single-parameter version for backward compatibility
|
|
156
|
-
*/
|
|
157
|
-
export function classifyTaskLegacy(task) {
|
|
158
|
-
return classifyTask(task, null);
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
/**
|
|
162
|
-
* Determine if a task result should escalate based on confidence and risk
|
|
163
|
-
*/
|
|
164
|
-
export function shouldEscalate(result, classification) {
|
|
165
|
-
// Always escalate if the model explicitly requests it
|
|
166
|
-
if (result.escalate === true) {
|
|
167
|
-
return true;
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
// Escalate low confidence results
|
|
171
|
-
if (result.confidence !== null && result.confidence < 0.5) {
|
|
172
|
-
return true;
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Escalate if task failed with errors
|
|
176
|
-
if (!result.success) {
|
|
177
|
-
return true;
|
|
178
|
-
}
|
|
179
|
-
|
|
180
|
-
// Escalate critical/high risk tasks with medium confidence
|
|
181
|
-
if ((classification.risk === 'critical' || classification.risk === 'high') &&
|
|
182
|
-
result.confidence !== null && result.confidence < 0.7) {
|
|
183
|
-
return true;
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
// Look for uncertainty indicators in the output
|
|
187
|
-
const uncertaintyWords = /\b(not sure|uncertain|don't know|unclear|confused|unsure|might|maybe|possibly)\b/i;
|
|
188
|
-
if (uncertaintyWords.test(result.output)) {
|
|
189
|
-
return true;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return false;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
/**
|
|
196
|
-
* Extract relevant keywords from task text
|
|
197
|
-
*/
|
|
198
|
-
function extractKeywords(text) {
|
|
199
|
-
const words = text.toLowerCase().split(/\s+/);
|
|
200
|
-
const relevantKeywords = [];
|
|
201
|
-
|
|
202
|
-
for (const pattern of RISK_KEYWORDS) {
|
|
203
|
-
const matches = text.match(pattern.regex);
|
|
204
|
-
if (matches) {
|
|
205
|
-
relevantKeywords.push(...matches.map(m => m.toLowerCase()));
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return [...new Set(relevantKeywords)]; // Remove duplicates
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
/**
|
|
213
|
-
* Extract mentioned files, enhanced with context
|
|
214
|
-
*/
|
|
215
|
-
function extractMentionedFiles(text, fileContext) {
|
|
216
|
-
const paths = extractPaths(text);
|
|
217
|
-
|
|
218
|
-
// If fileContext is provided, add related files
|
|
219
|
-
if (fileContext && fileContext.currentFiles) {
|
|
220
|
-
// Add files from current git status or file list
|
|
221
|
-
for (const file of fileContext.currentFiles) {
|
|
222
|
-
if (text.toLowerCase().includes(file.toLowerCase())) {
|
|
223
|
-
paths.push(file);
|
|
224
|
-
}
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
return [...new Set(paths)]; // Remove duplicates
|
|
229
|
-
}
|
|
230
|
-
|
|
231
|
-
/**
|
|
232
|
-
* Assess task complexity based on multiple indicators
|
|
233
|
-
*/
|
|
234
|
-
function assessComplexity(text) {
|
|
235
|
-
const lower = text.toLowerCase();
|
|
236
|
-
let complexity = 0;
|
|
237
|
-
|
|
238
|
-
// Length-based complexity
|
|
239
|
-
const wordCount = text.split(/\s+/).length;
|
|
240
|
-
if (wordCount > 50) complexity += 2;
|
|
241
|
-
else if (wordCount > 20) complexity += 1;
|
|
242
|
-
|
|
243
|
-
// Multi-action complexity
|
|
244
|
-
const actionWords = ['fix', 'add', 'remove', 'update', 'refactor', 'test', 'deploy'];
|
|
245
|
-
const actionCount = actionWords.filter(action => lower.includes(action)).length;
|
|
246
|
-
complexity += Math.min(actionCount, 3); // Cap at 3
|
|
247
|
-
|
|
248
|
-
// Technical complexity indicators
|
|
249
|
-
const complexPatterns = [
|
|
250
|
-
/\b(integration|migration|refactor|architecture|database|performance|optimization)\b/i,
|
|
251
|
-
/\b(concurrent|async|parallel|distributed|scalability)\b/i,
|
|
252
|
-
/\b(security|encryption|authentication|authorization)\b/i
|
|
253
|
-
];
|
|
254
|
-
|
|
255
|
-
complexity += complexPatterns.filter(pattern => pattern.test(text)).length;
|
|
256
|
-
|
|
257
|
-
return Math.min(complexity, 10); // Cap at 10
|
|
258
|
-
}
|
|
259
|
-
|
|
260
|
-
/**
|
|
261
|
-
* Classify risk based on task complexity
|
|
262
|
-
*/
|
|
263
|
-
function classifyComplexityRisk(complexity) {
|
|
264
|
-
if (complexity >= 7) {
|
|
265
|
-
return { level: 'high', reason: 'high complexity task' };
|
|
266
|
-
} else if (complexity >= 4) {
|
|
267
|
-
return { level: 'medium', reason: 'moderate complexity' };
|
|
268
|
-
} else {
|
|
269
|
-
return { level: 'low', reason: 'simple task' };
|
|
270
|
-
}
|
|
271
|
-
}
|
|
272
|
-
|
|
273
|
-
/**
|
|
274
|
-
* Estimate task confidence based on multiple signals
|
|
275
|
-
*/
|
|
276
|
-
function estimateTaskConfidence(keywords, complexity, paths, tier) {
|
|
277
|
-
let confidence = 0.7; // Base confidence
|
|
278
|
-
|
|
279
|
-
// Complexity penalty
|
|
280
|
-
if (complexity > 6) confidence -= 0.3;
|
|
281
|
-
else if (complexity > 3) confidence -= 0.1;
|
|
282
|
-
|
|
283
|
-
// Risk keyword penalty
|
|
284
|
-
const riskKeywords = keywords.filter(keyword =>
|
|
285
|
-
RISK_KEYWORDS.some(pattern =>
|
|
286
|
-
pattern.regex.test(keyword) && pattern.level !== 'low'
|
|
287
|
-
)
|
|
288
|
-
);
|
|
289
|
-
confidence -= riskKeywords.length * 0.1;
|
|
290
|
-
|
|
291
|
-
// Path-based adjustment
|
|
292
|
-
const sensitivePaths = paths.filter(path =>
|
|
293
|
-
path.includes('auth') ||
|
|
294
|
-
path.includes('secret') ||
|
|
295
|
-
path.includes('credential') ||
|
|
296
|
-
path.includes('billing')
|
|
297
|
-
);
|
|
298
|
-
confidence -= sensitivePaths.length * 0.15;
|
|
299
|
-
|
|
300
|
-
// Tier mismatch penalty
|
|
301
|
-
if (tier === 'worker' && complexity > 3) confidence -= 0.2;
|
|
302
|
-
if (tier === 'manager' && complexity < 2) confidence += 0.1;
|
|
303
|
-
|
|
304
|
-
return Math.max(0.1, Math.min(1.0, confidence));
|
|
305
|
-
}
|
|
306
|
-
|
|
307
|
-
/**
|
|
308
|
-
* Enhanced file risk classification
|
|
309
|
-
*/
|
|
310
|
-
function classifyFileRisk(paths) {
|
|
311
|
-
if (paths.length === 0) return { level: 'low', reason: 'no files mentioned' };
|
|
312
|
-
|
|
313
|
-
let highest = { level: 'low', reason: 'general files' };
|
|
314
|
-
|
|
315
|
-
for (const path of paths) {
|
|
316
|
-
const lowerPath = path.toLowerCase();
|
|
317
|
-
|
|
318
|
-
// Critical patterns
|
|
319
|
-
if (lowerPath.includes('.env') ||
|
|
320
|
-
lowerPath.includes('secret') ||
|
|
321
|
-
lowerPath.includes('credential') ||
|
|
322
|
-
lowerPath.includes('private') ||
|
|
323
|
-
lowerPath.includes('key')) {
|
|
324
|
-
return { level: 'critical', reason: `sensitive file (${path})` };
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
// High risk patterns
|
|
328
|
-
if (lowerPath.includes('auth') ||
|
|
329
|
-
lowerPath.includes('security') ||
|
|
330
|
-
lowerPath.includes('payment') ||
|
|
331
|
-
lowerPath.includes('billing') ||
|
|
332
|
-
lowerPath.includes('migration') ||
|
|
333
|
-
lowerPath.includes('schema')) {
|
|
334
|
-
highest = { level: 'high', reason: `sensitive directory (${path})` };
|
|
335
|
-
}
|
|
336
|
-
// Medium risk patterns
|
|
337
|
-
else if (lowerPath.includes('test') ||
|
|
338
|
-
lowerPath.includes('spec') ||
|
|
339
|
-
lowerPath.includes('config') ||
|
|
340
|
-
lowerPath.includes('api') ||
|
|
341
|
-
lowerPath.includes('server')) {
|
|
342
|
-
if (LEVEL_ORDER['medium'] > LEVEL_ORDER[highest.level]) {
|
|
343
|
-
highest = { level: 'medium', reason: `shared/infrastructure file (${path})` };
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
|
|
348
|
-
return highest;
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
/**
|
|
352
|
-
* Select the best available model for a given tier
|
|
353
|
-
* Now with enhanced provider selection
|
|
354
|
-
*/
|
|
355
|
-
export function selectModel(tier, availableModels) {
|
|
356
|
-
const tierModels = availableModels[tier] || [];
|
|
357
|
-
|
|
358
|
-
if (tierModels.length === 0) {
|
|
359
|
-
// Fallback: try to find any available model
|
|
360
|
-
const allModels = [...(availableModels.worker || []),
|
|
361
|
-
...(availableModels.ic || []),
|
|
362
|
-
...(availableModels.manager || [])];
|
|
363
|
-
return allModels[0] || null;
|
|
364
|
-
}
|
|
365
|
-
|
|
366
|
-
// Use intelligent provider selection if available
|
|
367
|
-
if (typeof selectProvider !== 'undefined') {
|
|
368
|
-
try {
|
|
369
|
-
const selected = selectProvider(tier, { availableModels });
|
|
370
|
-
if (selected) return selected;
|
|
371
|
-
} catch (error) {
|
|
372
|
-
console.warn('Provider selection failed, falling back to simple selection');
|
|
373
|
-
}
|
|
374
|
-
}
|
|
375
|
-
|
|
376
|
-
// Fallback: prefer models with better tier alignment
|
|
377
|
-
const tierPreferences = {
|
|
378
|
-
worker: ['claude', 'codex'],
|
|
379
|
-
ic: ['codex', 'claude'],
|
|
380
|
-
manager: ['claude', 'codex']
|
|
381
|
-
};
|
|
382
|
-
|
|
383
|
-
const preferences = tierPreferences[tier] || [];
|
|
384
|
-
for (const preferredProvider of preferences) {
|
|
385
|
-
const model = tierModels.find(m => m.provider === preferredProvider);
|
|
386
|
-
if (model) return model;
|
|
387
|
-
}
|
|
388
|
-
|
|
389
|
-
// Final fallback
|
|
390
|
-
return tierModels[0];
|
|
391
|
-
}
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* confidence.mjs — Parse model confidence output and handle structured responses
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Extract confidence data from model response
|
|
7
|
-
* Handles both structured JSON at the end and inline patterns
|
|
8
|
-
*/
|
|
9
|
-
export function parseConfidence(output) {
|
|
10
|
-
if (!output || typeof output !== 'string') {
|
|
11
|
-
return {
|
|
12
|
-
confidence: null,
|
|
13
|
-
escalate: false,
|
|
14
|
-
reason: 'no output',
|
|
15
|
-
needsReview: false,
|
|
16
|
-
structured: false
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Try to extract structured JSON from end of response
|
|
21
|
-
const jsonMatch = output.match(/\{[^{}]*"confidence"[^{}]*\}(?:\s*$)/);
|
|
22
|
-
|
|
23
|
-
if (jsonMatch) {
|
|
24
|
-
try {
|
|
25
|
-
const data = JSON.parse(jsonMatch[0]);
|
|
26
|
-
return {
|
|
27
|
-
confidence: parseFloat(data.confidence) || 0,
|
|
28
|
-
escalate: data.escalate === true || data.escalate === 'true',
|
|
29
|
-
reason: data.reason || 'structured response',
|
|
30
|
-
needsReview: data.needs_review === true || data.needs_review === 'true',
|
|
31
|
-
structured: true,
|
|
32
|
-
rawData: data
|
|
33
|
-
};
|
|
34
|
-
} catch (error) {
|
|
35
|
-
// Fall through to pattern-based parsing
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
// Fallback: estimate confidence from response patterns
|
|
40
|
-
return estimateConfidenceFromText(output);
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/**
|
|
44
|
-
* Estimate confidence from text patterns when structured output is missing
|
|
45
|
-
*/
|
|
46
|
-
function estimateConfidenceFromText(text) {
|
|
47
|
-
const lower = text.toLowerCase();
|
|
48
|
-
|
|
49
|
-
// High confidence indicators
|
|
50
|
-
const highConfidence = [
|
|
51
|
-
'definitely', 'certain', 'sure', 'confident', 'obviously',
|
|
52
|
-
'clearly', 'exactly', 'precisely', 'completed successfully'
|
|
53
|
-
];
|
|
54
|
-
|
|
55
|
-
// Medium confidence indicators
|
|
56
|
-
const mediumConfidence = [
|
|
57
|
-
'likely', 'probably', 'should work', 'appears to', 'seems like',
|
|
58
|
-
'generally', 'typically', 'usually'
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// Low confidence / uncertainty indicators
|
|
62
|
-
const lowConfidence = [
|
|
63
|
-
'not sure', 'uncertain', "don't know", 'unclear', 'confused',
|
|
64
|
-
'unsure', 'might', 'maybe', 'possibly', 'perhaps', 'could be',
|
|
65
|
-
'need to check', 'requires investigation', 'hard to tell'
|
|
66
|
-
];
|
|
67
|
-
|
|
68
|
-
// Escalation indicators
|
|
69
|
-
const escalationWords = [
|
|
70
|
-
'complex', 'complicated', 'difficult', 'needs review',
|
|
71
|
-
'architecture decision', 'security concern', 'not my area',
|
|
72
|
-
'beyond my scope', 'manager should', 'escalate'
|
|
73
|
-
];
|
|
74
|
-
|
|
75
|
-
let confidence = 0.6; // default neutral
|
|
76
|
-
let escalate = false;
|
|
77
|
-
let reason = 'text analysis';
|
|
78
|
-
|
|
79
|
-
// Check for explicit escalation requests
|
|
80
|
-
if (escalationWords.some(word => lower.includes(word))) {
|
|
81
|
-
escalate = true;
|
|
82
|
-
confidence = Math.min(confidence, 0.4);
|
|
83
|
-
reason = 'explicit escalation request';
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
// Adjust based on confidence indicators
|
|
87
|
-
if (lowConfidence.some(word => lower.includes(word))) {
|
|
88
|
-
confidence = Math.min(confidence, 0.3);
|
|
89
|
-
escalate = true;
|
|
90
|
-
reason = 'uncertainty indicators';
|
|
91
|
-
} else if (highConfidence.some(word => lower.includes(word))) {
|
|
92
|
-
confidence = Math.max(confidence, 0.8);
|
|
93
|
-
reason = 'high confidence indicators';
|
|
94
|
-
} else if (mediumConfidence.some(word => lower.includes(word))) {
|
|
95
|
-
confidence = 0.6;
|
|
96
|
-
reason = 'medium confidence indicators';
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
// Check for error patterns
|
|
100
|
-
const errorPatterns = [
|
|
101
|
-
/error/i, /failed/i, /couldn't/i, /unable to/i, /permission denied/i
|
|
102
|
-
];
|
|
103
|
-
|
|
104
|
-
if (errorPatterns.some(pattern => pattern.test(text))) {
|
|
105
|
-
confidence = 0.2;
|
|
106
|
-
escalate = true;
|
|
107
|
-
reason = 'error detected';
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
return {
|
|
111
|
-
confidence,
|
|
112
|
-
escalate,
|
|
113
|
-
reason,
|
|
114
|
-
needsReview: confidence < 0.5,
|
|
115
|
-
structured: false
|
|
116
|
-
};
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
/**
|
|
120
|
-
* Validate confidence score is within expected range
|
|
121
|
-
*/
|
|
122
|
-
export function validateConfidence(confidence) {
|
|
123
|
-
if (confidence === null || confidence === undefined) return null;
|
|
124
|
-
|
|
125
|
-
const parsed = parseFloat(confidence);
|
|
126
|
-
if (isNaN(parsed)) return null;
|
|
127
|
-
|
|
128
|
-
// Clamp to valid range
|
|
129
|
-
return Math.max(0, Math.min(1, parsed));
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Determine if a task result should escalate based on confidence and context
|
|
134
|
-
*/
|
|
135
|
-
export function shouldEscalateOnConfidence(confidence, riskLevel, tier) {
|
|
136
|
-
if (confidence === null) return false;
|
|
137
|
-
|
|
138
|
-
// Always escalate very low confidence
|
|
139
|
-
if (confidence < 0.3) return true;
|
|
140
|
-
|
|
141
|
-
// Risk-based thresholds
|
|
142
|
-
const thresholds = {
|
|
143
|
-
critical: 0.8,
|
|
144
|
-
high: 0.7,
|
|
145
|
-
medium: 0.5,
|
|
146
|
-
low: 0.4
|
|
147
|
-
};
|
|
148
|
-
|
|
149
|
-
const threshold = thresholds[riskLevel] || thresholds.medium;
|
|
150
|
-
return confidence < threshold;
|
|
151
|
-
}
|