tycono 0.3.22-beta.0 → 0.3.22-beta.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/package.json
CHANGED
|
@@ -13,6 +13,7 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import { executionManager, type Execution } from './execution-manager.js';
|
|
15
15
|
import { createSession, getSession, listSessions, addMessage, type Message } from './session-store.js';
|
|
16
|
+
import Anthropic from '@anthropic-ai/sdk';
|
|
16
17
|
import { buildOrgTree, getSubordinates } from '../engine/org-tree.js';
|
|
17
18
|
import fs from 'node:fs';
|
|
18
19
|
import path from 'node:path';
|
|
@@ -226,14 +227,15 @@ class SupervisorHeartbeat {
|
|
|
226
227
|
}
|
|
227
228
|
state.crashCount = 0;
|
|
228
229
|
|
|
229
|
-
// Dual Mode: Conversation vs Dispatch
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
230
|
+
// Dual Mode: Conversation vs Dispatch
|
|
231
|
+
// AI classifies the directive (Haiku), falls back to regex
|
|
232
|
+
this.classifyDirective(text).then(isConversation => {
|
|
233
|
+
if (isConversation) {
|
|
234
|
+
this.spawnConversation(state, text);
|
|
235
|
+
} else {
|
|
236
|
+
this.scheduleRestart(state, 0);
|
|
237
|
+
}
|
|
238
|
+
});
|
|
237
239
|
}
|
|
238
240
|
|
|
239
241
|
return directive;
|
|
@@ -321,33 +323,68 @@ class SupervisorHeartbeat {
|
|
|
321
323
|
/* ─── Internal: Dual Mode ─────────────────── */
|
|
322
324
|
|
|
323
325
|
/**
|
|
324
|
-
*
|
|
326
|
+
* Classify: is this directive a question/status check (conversation)
|
|
325
327
|
* or a work task (needs dispatch)?
|
|
326
328
|
*
|
|
327
|
-
*
|
|
328
|
-
*
|
|
329
|
+
* Uses Haiku LLM for classification when ANTHROPIC_API_KEY is available.
|
|
330
|
+
* Falls back to regex heuristic when no API key.
|
|
329
331
|
*/
|
|
330
|
-
private
|
|
332
|
+
private async classifyDirective(text: string): Promise<boolean> {
|
|
333
|
+
// Try AI classification first (fast, accurate, language-agnostic)
|
|
334
|
+
if (process.env.ANTHROPIC_API_KEY) {
|
|
335
|
+
try {
|
|
336
|
+
const result = await this.classifyWithHaiku(text);
|
|
337
|
+
console.log(`[Supervisor] AI classified "${text.slice(0, 40)}" as ${result ? 'conversation' : 'task'}`);
|
|
338
|
+
return result;
|
|
339
|
+
} catch (err) {
|
|
340
|
+
console.warn(`[Supervisor] AI classification failed, falling back to regex:`, err);
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Fallback: regex heuristic
|
|
345
|
+
return this.isConversationDirectiveFallback(text);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
private async classifyWithHaiku(text: string): Promise<boolean> {
|
|
349
|
+
const client = new Anthropic();
|
|
350
|
+
const response = await client.messages.create({
|
|
351
|
+
model: 'claude-haiku-4-5-20251001',
|
|
352
|
+
max_tokens: 1,
|
|
353
|
+
system: `You classify user messages to a CEO AI assistant.
|
|
354
|
+
Reply with exactly one character:
|
|
355
|
+
- "Q" if the message is a question, status check, or casual conversation (no action needed)
|
|
356
|
+
- "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.)
|
|
357
|
+
|
|
358
|
+
Examples:
|
|
359
|
+
"뭐 했어?" → Q
|
|
360
|
+
"CBO한테 일 줘" → T
|
|
361
|
+
"시장 조사해" → T
|
|
362
|
+
"현재 상태 알려줘" → Q
|
|
363
|
+
"게임 만들어 CTO에게 시켜" → T
|
|
364
|
+
"how's it going?" → Q
|
|
365
|
+
"deploy the app" → T`,
|
|
366
|
+
messages: [{ role: 'user', content: text }],
|
|
367
|
+
});
|
|
368
|
+
const reply = (response.content[0] as { type: 'text'; text: string }).text.trim();
|
|
369
|
+
return reply === 'Q';
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
private isConversationDirectiveFallback(text: string): boolean {
|
|
331
373
|
const t = text.trim();
|
|
332
374
|
|
|
333
375
|
// Short messages with question marks → conversation
|
|
334
376
|
if (t.includes('?') && t.length < 100) return true;
|
|
335
377
|
|
|
336
|
-
// Task patterns
|
|
378
|
+
// Task patterns — action verbs override
|
|
337
379
|
const taskPatterns = [
|
|
338
380
|
/만들어/, /구현해/, /개발해/, /수정해/, /변경해/, /리팩토링/,
|
|
339
381
|
/설계해/, /작성해/, /배포해/, /테스트해/, /고쳐/, /해줘/, /해봐/,
|
|
340
382
|
/진행시켜/, /진행해/, /시작해/, /실행해/, /돌려/,
|
|
383
|
+
/시켜/, /맡겨/, /일\s*줘/, /지시해/, /분석해/, /조사해/, /검토해/,
|
|
384
|
+
/에게\s*(시|맡|줘)/, /한테\s*(시|맡|줘)/,
|
|
341
385
|
/build/i, /create/i, /implement/i, /develop/i, /fix/i, /deploy/i, /refactor/i,
|
|
342
386
|
/proceed/i, /start/i, /execute/i, /run/i, /do it/i, /go ahead/i,
|
|
343
|
-
|
|
344
|
-
if (taskPatterns.some(p => p.test(t))) return false;
|
|
345
|
-
|
|
346
|
-
// Korean question patterns
|
|
347
|
-
const questionPatterns = [
|
|
348
|
-
/확인해/, /알려줘/, /보여줘/, /어때/, /뭐야/, /뭐지/, /뭘까/,
|
|
349
|
-
/상태/, /상황/, /현재/, /어디/, /얼마/,
|
|
350
|
-
/what/i, /how.*going/i, /status/i, /check/i, /show/i, /tell/i,
|
|
387
|
+
/assign/i, /dispatch/i, /delegate/i, /tell.*to/i, /ask.*to/i,
|
|
351
388
|
];
|
|
352
389
|
if (taskPatterns.some(p => p.test(t))) return false;
|
|
353
390
|
|