tycono 0.3.30 → 0.3.31
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/package.json
CHANGED
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
import { executionManager, type Execution } from './execution-manager.js';
|
|
15
15
|
import { createSession, getSession, listSessions, addMessage, type Message } from './session-store.js';
|
|
16
16
|
import Anthropic from '@anthropic-ai/sdk';
|
|
17
|
+
import { ClaudeCliProvider } from '../engine/llm-adapter.js';
|
|
17
18
|
import { buildOrgTree, getSubordinates } from '../engine/org-tree.js';
|
|
19
|
+
import { readConfig } from './company-config.js';
|
|
18
20
|
import fs from 'node:fs';
|
|
19
21
|
import path from 'node:path';
|
|
20
22
|
import { COMPANY_ROOT } from './file-reader.js';
|
|
@@ -332,28 +334,7 @@ class SupervisorHeartbeat {
|
|
|
332
334
|
* Uses Haiku LLM for classification when ANTHROPIC_API_KEY is available.
|
|
333
335
|
* Falls back to regex heuristic when no API key.
|
|
334
336
|
*/
|
|
335
|
-
private
|
|
336
|
-
// Try AI classification first (fast, accurate, language-agnostic)
|
|
337
|
-
if (process.env.ANTHROPIC_API_KEY) {
|
|
338
|
-
try {
|
|
339
|
-
const result = await this.classifyWithHaiku(text);
|
|
340
|
-
console.log(`[Supervisor] AI classified "${text.slice(0, 40)}" as ${result ? 'conversation' : 'task'}`);
|
|
341
|
-
return result;
|
|
342
|
-
} catch (err) {
|
|
343
|
-
console.warn(`[Supervisor] AI classification failed, falling back to regex:`, err);
|
|
344
|
-
}
|
|
345
|
-
}
|
|
346
|
-
|
|
347
|
-
// Fallback: regex heuristic
|
|
348
|
-
return this.isConversationDirectiveFallback(text);
|
|
349
|
-
}
|
|
350
|
-
|
|
351
|
-
private async classifyWithHaiku(text: string): Promise<boolean> {
|
|
352
|
-
const client = new Anthropic();
|
|
353
|
-
const response = await client.messages.create({
|
|
354
|
-
model: 'claude-haiku-4-5-20251001',
|
|
355
|
-
max_tokens: 1,
|
|
356
|
-
system: `You classify user messages to a CEO AI assistant.
|
|
337
|
+
private static readonly CLASSIFY_SYSTEM = `You classify user messages to a CEO AI assistant.
|
|
357
338
|
Reply with exactly one character:
|
|
358
339
|
- "Q" if the message is a question, status check, or casual conversation (no action needed)
|
|
359
340
|
- "T" if the message is a task, work instruction, delegation request, or any directive that requires action (creating, building, fixing, assigning work to team members, etc.)
|
|
@@ -365,11 +346,45 @@ Examples:
|
|
|
365
346
|
"현재 상태 알려줘" → Q
|
|
366
347
|
"게임 만들어 CTO에게 시켜" → T
|
|
367
348
|
"how's it going?" → Q
|
|
368
|
-
"deploy the app" → T
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
349
|
+
"deploy the app" → T`;
|
|
350
|
+
|
|
351
|
+
private async classifyDirective(text: string): Promise<boolean> {
|
|
352
|
+
// Try AI classification (fast, accurate, language-agnostic)
|
|
353
|
+
try {
|
|
354
|
+
const config = readConfig(COMPANY_ROOT);
|
|
355
|
+
const engine = config.engine || process.env.EXECUTION_ENGINE || 'claude-cli';
|
|
356
|
+
|
|
357
|
+
let reply: string;
|
|
358
|
+
if (engine === 'claude-cli') {
|
|
359
|
+
// Claude CLI (Claude Max) — use claude -p with haiku model
|
|
360
|
+
const provider = new ClaudeCliProvider({ model: 'claude-haiku-4-5-20251001' });
|
|
361
|
+
const response = await provider.chat(
|
|
362
|
+
SupervisorHeartbeat.CLASSIFY_SYSTEM,
|
|
363
|
+
[{ role: 'user', content: text }],
|
|
364
|
+
);
|
|
365
|
+
reply = response.content.find(c => c.type === 'text')?.text?.trim() ?? '';
|
|
366
|
+
} else if (process.env.ANTHROPIC_API_KEY) {
|
|
367
|
+
// BYOK — use Anthropic SDK directly
|
|
368
|
+
const client = new Anthropic();
|
|
369
|
+
const response = await client.messages.create({
|
|
370
|
+
model: 'claude-haiku-4-5-20251001',
|
|
371
|
+
max_tokens: 1,
|
|
372
|
+
system: SupervisorHeartbeat.CLASSIFY_SYSTEM,
|
|
373
|
+
messages: [{ role: 'user', content: text }],
|
|
374
|
+
});
|
|
375
|
+
reply = (response.content[0] as { type: 'text'; text: string }).text.trim();
|
|
376
|
+
} else {
|
|
377
|
+
// No engine available — regex fallback
|
|
378
|
+
return this.isConversationDirectiveFallback(text);
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
const isConversation = reply === 'Q';
|
|
382
|
+
console.log(`[Supervisor] AI classified "${text.slice(0, 40)}" as ${isConversation ? 'conversation' : 'task'} (engine=${engine})`);
|
|
383
|
+
return isConversation;
|
|
384
|
+
} catch (err) {
|
|
385
|
+
console.warn(`[Supervisor] AI classification failed, falling back to regex:`, err);
|
|
386
|
+
return this.isConversationDirectiveFallback(text);
|
|
387
|
+
}
|
|
373
388
|
}
|
|
374
389
|
|
|
375
390
|
private isConversationDirectiveFallback(text: string): boolean {
|