triflux 10.43.0 → 10.44.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/README.md +2 -0
- package/adapters/codex/skills/tfx-harness/SKILL.md +30 -0
- package/adapters/codex/skills/tfx-harness/skill.json +5 -0
- package/bin/triflux.mjs +14 -0
- package/hooks/keyword-rules.json +139 -19
- package/hub/cli-adapter-base.mjs +11 -2
- package/hub/codex-adapter.mjs +3 -0
- package/hub/intent.mjs +24 -32
- package/hub/router.mjs +272 -0
- package/hub/schema.sql +61 -2
- package/hub/server.mjs +42 -0
- package/hub/store.mjs +577 -5
- package/hub/team/conductor.mjs +23 -2
- package/hub/team/execution-mode.mjs +12 -2
- package/hub/team/headless.mjs +16 -0
- package/hub/team/retry-state-machine.mjs +8 -3
- package/hub/team/swarm-hypervisor.mjs +1 -0
- package/hub/team/swarm-preflight.mjs +47 -0
- package/hub/team/synapse-http.mjs +149 -4
- package/hub/team/worktree-lifecycle.mjs +56 -59
- package/hub/tools.mjs +11 -0
- package/hub/workers/codex-mcp.mjs +20 -4
- package/hub/workers/delegator-mcp.mjs +3 -49
- package/package.json +2 -1
- package/scripts/__tests__/lint-skills.test.mjs +68 -0
- package/scripts/__tests__/tfx-route-node-entry.test.mjs +36 -0
- package/scripts/keyword-detector.mjs +55 -8
- package/scripts/lib/agent-route-policy.mjs +360 -0
- package/scripts/lib/cli-codex.mjs +22 -160
- package/scripts/lib/codex-profile-config.mjs +29 -3
- package/scripts/lib/keyword-rules.mjs +12 -0
- package/scripts/lint-skills.mjs +65 -0
- package/scripts/pack.mjs +13 -0
- package/scripts/release/check-packages-mirror.mjs +5 -0
- package/scripts/setup.mjs +94 -2
- package/scripts/tfx-route.mjs +14 -1
- package/scripts/tfx-route.sh +233 -70
- package/skills/tfx-harness/SKILL.md +19 -76
- package/skills/tfx-hub/SKILL.md +1 -1
- package/skills/tfx-interview/SKILL.md +3 -1
- package/skills/tfx-interview/skill.json +1 -13
- package/skills/tfx-profile/SKILL.md +25 -15
- package/skills/tfx-prune/SKILL.md +3 -1
- package/skills/tfx-prune/skill.json +1 -8
- package/skills/tfx-setup/SKILL.md +1 -1
- package/tui/codex-profile.mjs +11 -2
- package/tui/setup.mjs +2 -0
package/README.md
CHANGED
|
@@ -264,6 +264,8 @@ state without replaying the entire conversation.
|
|
|
264
264
|
|
|
265
265
|
## Architecture
|
|
266
266
|
|
|
267
|
+
> 상세 구조·패키지 레이아웃·실행 경로는 [ARCHITECTURE.md](ARCHITECTURE.md), 문서 전체 지도는 [docs/README.md](docs/README.md) 참조.
|
|
268
|
+
|
|
267
269
|
<p align="center">
|
|
268
270
|
<img src="docs/assets/architecture.svg" alt="triflux architecture" width="680">
|
|
269
271
|
</p>
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: tfx-harness
|
|
3
|
+
description: >
|
|
4
|
+
Use for meta-routing questions. Read the canonical routing SSOT and return
|
|
5
|
+
exactly one branch and immediate owner; do not execute the requested work.
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# tfx-harness — Codex adapter
|
|
9
|
+
|
|
10
|
+
Read `.claude/rules/tfx-routing.md` D0–D11 before routing. This adapter only
|
|
11
|
+
translates host syntax: use `$skill` for an available owner. Do not copy the
|
|
12
|
+
routing tree, keyword rules, or an owner matrix here.
|
|
13
|
+
|
|
14
|
+
Return:
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
[tfx-harness]
|
|
18
|
+
branch: D<n>
|
|
19
|
+
owner: <exactly one immediate owner>
|
|
20
|
+
availability: available | unavailable | unknown
|
|
21
|
+
fallback_notice: <optional>
|
|
22
|
+
status: recommendation-only | dispatching | blocked
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
- Never choose more than one branch or immediate owner.
|
|
26
|
+
- With unknown availability, do not infer a fallback. With measured
|
|
27
|
+
unavailability, state `owner unavailable → tfx-X fallback` before fallback.
|
|
28
|
+
- If the SSOT cannot be read, return `blocked: routing SSOT unavailable`.
|
|
29
|
+
- For a “which skill/path?” question, remain recommendation-only.
|
|
30
|
+
- Do not select downstream implementation agents or models.
|
package/bin/triflux.mjs
CHANGED
|
@@ -94,6 +94,7 @@ import {
|
|
|
94
94
|
SKILL_ALIASES,
|
|
95
95
|
SYNC_MAP,
|
|
96
96
|
syncAliasedSkillDir,
|
|
97
|
+
syncCodexHarnessAdapter,
|
|
97
98
|
} from "../scripts/setup.mjs";
|
|
98
99
|
import { cleanupTmpFiles } from "../scripts/tmp-cleanup.mjs";
|
|
99
100
|
|
|
@@ -2203,6 +2204,19 @@ function cmdSetup(options = {}) {
|
|
|
2203
2204
|
}
|
|
2204
2205
|
}
|
|
2205
2206
|
|
|
2207
|
+
const codexHarnessSync = syncCodexHarnessAdapter();
|
|
2208
|
+
if (!codexHarnessSync.ok) {
|
|
2209
|
+
fail(`Codex tfx-harness: ${codexHarnessSync.reason}`);
|
|
2210
|
+
return;
|
|
2211
|
+
}
|
|
2212
|
+
if (codexHarnessSync.action === "synced") {
|
|
2213
|
+
ok("Codex tfx-harness adapter: 동기화됨");
|
|
2214
|
+
} else if (codexHarnessSync.action === "skipped") {
|
|
2215
|
+
warn(
|
|
2216
|
+
`Codex tfx-harness adapter: 사용자 스킬 보존 (backup: ${codexHarnessSync.backupDir})`,
|
|
2217
|
+
);
|
|
2218
|
+
}
|
|
2219
|
+
|
|
2206
2220
|
// ── psmux 기본 셸 자동 수정 (cmd.exe → PowerShell) ──
|
|
2207
2221
|
if (process.platform === "win32" && which("psmux")) {
|
|
2208
2222
|
try {
|
package/hooks/keyword-rules.json
CHANGED
|
@@ -96,6 +96,102 @@
|
|
|
96
96
|
"state": null,
|
|
97
97
|
"mcp_route": null
|
|
98
98
|
},
|
|
99
|
+
{
|
|
100
|
+
"id": "tfx-review",
|
|
101
|
+
"patterns": [
|
|
102
|
+
{
|
|
103
|
+
"source": "\\btfx[\\s-]?review\\b",
|
|
104
|
+
"flags": "i"
|
|
105
|
+
}
|
|
106
|
+
],
|
|
107
|
+
"skill": "tfx-review",
|
|
108
|
+
"priority": 1,
|
|
109
|
+
"supersedes": ["tfx-unified"],
|
|
110
|
+
"exclusive": false,
|
|
111
|
+
"state": null,
|
|
112
|
+
"mcp_route": null,
|
|
113
|
+
"explicit": true
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
"id": "tfx-analysis",
|
|
117
|
+
"patterns": [
|
|
118
|
+
{
|
|
119
|
+
"source": "\\btfx[\\s-]?analysis\\b",
|
|
120
|
+
"flags": "i"
|
|
121
|
+
}
|
|
122
|
+
],
|
|
123
|
+
"skill": "tfx-analysis",
|
|
124
|
+
"priority": 1,
|
|
125
|
+
"supersedes": ["tfx-unified"],
|
|
126
|
+
"exclusive": false,
|
|
127
|
+
"state": null,
|
|
128
|
+
"mcp_route": null,
|
|
129
|
+
"explicit": true
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
"id": "tfx-plan",
|
|
133
|
+
"patterns": [
|
|
134
|
+
{
|
|
135
|
+
"source": "\\btfx[\\s-]?plan\\b",
|
|
136
|
+
"flags": "i"
|
|
137
|
+
}
|
|
138
|
+
],
|
|
139
|
+
"skill": "tfx-plan",
|
|
140
|
+
"priority": 1,
|
|
141
|
+
"supersedes": ["tfx-unified"],
|
|
142
|
+
"exclusive": false,
|
|
143
|
+
"state": null,
|
|
144
|
+
"mcp_route": null,
|
|
145
|
+
"explicit": true
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
"id": "tfx-qa",
|
|
149
|
+
"patterns": [
|
|
150
|
+
{
|
|
151
|
+
"source": "\\btfx[\\s-]?qa\\b",
|
|
152
|
+
"flags": "i"
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
"skill": "tfx-qa",
|
|
156
|
+
"priority": 1,
|
|
157
|
+
"supersedes": ["tfx-unified"],
|
|
158
|
+
"exclusive": false,
|
|
159
|
+
"state": null,
|
|
160
|
+
"mcp_route": null,
|
|
161
|
+
"explicit": true
|
|
162
|
+
},
|
|
163
|
+
{
|
|
164
|
+
"id": "tfx-research",
|
|
165
|
+
"patterns": [
|
|
166
|
+
{
|
|
167
|
+
"source": "\\btfx[\\s-]?research\\b",
|
|
168
|
+
"flags": "i"
|
|
169
|
+
}
|
|
170
|
+
],
|
|
171
|
+
"skill": "tfx-research",
|
|
172
|
+
"priority": 1,
|
|
173
|
+
"supersedes": ["tfx-unified"],
|
|
174
|
+
"exclusive": false,
|
|
175
|
+
"state": null,
|
|
176
|
+
"mcp_route": null,
|
|
177
|
+
"explicit": true
|
|
178
|
+
},
|
|
179
|
+
{
|
|
180
|
+
"id": "tfx-find",
|
|
181
|
+
"patterns": [
|
|
182
|
+
{
|
|
183
|
+
"source": "\\btfx[\\s-]?find\\b",
|
|
184
|
+
"flags": "i"
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
"skill": "tfx-find",
|
|
188
|
+
"priority": 1,
|
|
189
|
+
"supersedes": ["tfx-unified"],
|
|
190
|
+
"exclusive": false,
|
|
191
|
+
"state": null,
|
|
192
|
+
"mcp_route": null,
|
|
193
|
+
"explicit": true
|
|
194
|
+
},
|
|
99
195
|
{
|
|
100
196
|
"id": "tfx-unified",
|
|
101
197
|
"patterns": [
|
|
@@ -127,10 +223,6 @@
|
|
|
127
223
|
"source": "(?:찾아봐|조사해|검색해)",
|
|
128
224
|
"flags": "i"
|
|
129
225
|
},
|
|
130
|
-
{
|
|
131
|
-
"source": "(?:정리해|슬롭|클린업)",
|
|
132
|
-
"flags": "i"
|
|
133
|
-
},
|
|
134
226
|
{
|
|
135
227
|
"source": "(?:병렬|동시에|parallel|concurrent)",
|
|
136
228
|
"flags": "i"
|
|
@@ -155,6 +247,41 @@
|
|
|
155
247
|
"state": null,
|
|
156
248
|
"mcp_route": null
|
|
157
249
|
},
|
|
250
|
+
{
|
|
251
|
+
"id": "host-ai-slop-cleaner",
|
|
252
|
+
"patterns": [
|
|
253
|
+
{
|
|
254
|
+
"source": "(?:AI\\s*슬롭|ai\\s*slop|anti[\\s-]?slop|deslop)",
|
|
255
|
+
"flags": "i"
|
|
256
|
+
},
|
|
257
|
+
{
|
|
258
|
+
"source": "(?:슬롭|클린업)",
|
|
259
|
+
"flags": "i"
|
|
260
|
+
}
|
|
261
|
+
],
|
|
262
|
+
"skill": "ai-slop-cleaner",
|
|
263
|
+
"priority": 1,
|
|
264
|
+
"supersedes": [],
|
|
265
|
+
"exclusive": false,
|
|
266
|
+
"state": null,
|
|
267
|
+
"mcp_route": null
|
|
268
|
+
},
|
|
269
|
+
{
|
|
270
|
+
"id": "tfx-prune",
|
|
271
|
+
"patterns": [
|
|
272
|
+
{
|
|
273
|
+
"source": "\\btfx[\\s-]?prune\\b",
|
|
274
|
+
"flags": "i"
|
|
275
|
+
}
|
|
276
|
+
],
|
|
277
|
+
"skill": "tfx-prune",
|
|
278
|
+
"priority": 1,
|
|
279
|
+
"supersedes": ["tfx-unified"],
|
|
280
|
+
"exclusive": false,
|
|
281
|
+
"state": null,
|
|
282
|
+
"mcp_route": null,
|
|
283
|
+
"explicit": true
|
|
284
|
+
},
|
|
158
285
|
{
|
|
159
286
|
"id": "tfx-codex",
|
|
160
287
|
"patterns": [
|
|
@@ -586,7 +713,6 @@
|
|
|
586
713
|
},
|
|
587
714
|
{
|
|
588
715
|
"id": "gstack-ship",
|
|
589
|
-
"disabled": true,
|
|
590
716
|
"patterns": [
|
|
591
717
|
{
|
|
592
718
|
"source": "(?:배포해|PR\\s*만들|릴리스\\s*해|머지하고\\s*배포)",
|
|
@@ -598,7 +724,7 @@
|
|
|
598
724
|
}
|
|
599
725
|
],
|
|
600
726
|
"skill": "ship",
|
|
601
|
-
"priority":
|
|
727
|
+
"priority": 1,
|
|
602
728
|
"supersedes": [],
|
|
603
729
|
"exclusive": false,
|
|
604
730
|
"state": null,
|
|
@@ -627,12 +753,12 @@
|
|
|
627
753
|
"id": "gstack-cso",
|
|
628
754
|
"patterns": [
|
|
629
755
|
{
|
|
630
|
-
"source": "(?:보안\\s*(
|
|
756
|
+
"source": "(?:보안\\s*(?:감사|점검|리뷰|검토|스캔)|\\bcso\\b|\\bOWASP\\b|\\bSTRIDE\\b)",
|
|
631
757
|
"flags": "i"
|
|
632
758
|
}
|
|
633
759
|
],
|
|
634
760
|
"skill": "cso",
|
|
635
|
-
"priority":
|
|
761
|
+
"priority": 1,
|
|
636
762
|
"supersedes": [],
|
|
637
763
|
"exclusive": false,
|
|
638
764
|
"state": null,
|
|
@@ -651,7 +777,7 @@
|
|
|
651
777
|
}
|
|
652
778
|
],
|
|
653
779
|
"skill": "qa",
|
|
654
|
-
"priority":
|
|
780
|
+
"priority": 1,
|
|
655
781
|
"supersedes": [],
|
|
656
782
|
"exclusive": false,
|
|
657
783
|
"state": null,
|
|
@@ -722,14 +848,6 @@
|
|
|
722
848
|
"source": "/ship\\b",
|
|
723
849
|
"flags": "i"
|
|
724
850
|
},
|
|
725
|
-
{
|
|
726
|
-
"source": "\\brelease\\b",
|
|
727
|
-
"flags": "i"
|
|
728
|
-
},
|
|
729
|
-
{
|
|
730
|
-
"source": "\\bpublish\\b",
|
|
731
|
-
"flags": "i"
|
|
732
|
-
},
|
|
733
851
|
{
|
|
734
852
|
"source": "배포(?!자|사|장|처)",
|
|
735
853
|
"flags": ""
|
|
@@ -744,11 +862,13 @@
|
|
|
744
862
|
}
|
|
745
863
|
],
|
|
746
864
|
"skill": "tfx-ship",
|
|
747
|
-
"priority":
|
|
865
|
+
"priority": 1,
|
|
748
866
|
"supersedes": ["gstack-ship"],
|
|
749
867
|
"exclusive": false,
|
|
750
868
|
"state": null,
|
|
751
|
-
"mcp_route": null
|
|
869
|
+
"mcp_route": null,
|
|
870
|
+
"repo_scope": ["triflux"],
|
|
871
|
+
"explicit": true
|
|
752
872
|
}
|
|
753
873
|
]
|
|
754
874
|
}
|
package/hub/cli-adapter-base.mjs
CHANGED
|
@@ -167,7 +167,7 @@ export const CODEX_MCP_EXECUTION_EXIT_CODE = 1;
|
|
|
167
167
|
*
|
|
168
168
|
* @param {string} prompt
|
|
169
169
|
* @param {string|null} resultFile — null이면 --output-last-message 생략
|
|
170
|
-
* @param {{ profile?: string, skipGitRepoCheck?: boolean, sandboxBypass?: boolean, cwd?: string, mcpServers?: string[], stdinPrompt?: boolean }} [opts]
|
|
170
|
+
* @param {{ profile?: string, codexHome?: string, disallowUltra?: boolean, enforceCanonicalProfile?: boolean, skipGitRepoCheck?: boolean, sandboxBypass?: boolean, cwd?: string, mcpServers?: string[], stdinPrompt?: boolean }} [opts]
|
|
171
171
|
* @returns {string} 실행할 셸 커맨드
|
|
172
172
|
*/
|
|
173
173
|
export function buildExecCommand(prompt, resultFile = null, opts = {}) {
|
|
@@ -177,6 +177,9 @@ export function buildExecCommand(prompt, resultFile = null, opts = {}) {
|
|
|
177
177
|
sandboxBypass = true,
|
|
178
178
|
mcpServers,
|
|
179
179
|
stdinPrompt,
|
|
180
|
+
codexHome,
|
|
181
|
+
disallowUltra,
|
|
182
|
+
enforceCanonicalProfile,
|
|
180
183
|
} = opts;
|
|
181
184
|
|
|
182
185
|
const parts = ["codex"];
|
|
@@ -185,7 +188,13 @@ export function buildExecCommand(prompt, resultFile = null, opts = {}) {
|
|
|
185
188
|
// still contains an inline [profiles.X] table (and codex re-injects such
|
|
186
189
|
// tables when it rewrites config.toml), so the `-c model=.. -c
|
|
187
190
|
// model_reasoning_effort=..` form is immune and mutates no config.
|
|
188
|
-
const profileOverrides = profile
|
|
191
|
+
const profileOverrides = profile
|
|
192
|
+
? codexProfileConfigOverrides(profile, {
|
|
193
|
+
codexHome,
|
|
194
|
+
disallowUltra,
|
|
195
|
+
enforceCanonicalProfile,
|
|
196
|
+
})
|
|
197
|
+
: [];
|
|
189
198
|
|
|
190
199
|
if (FEATURES.execSubcommand) {
|
|
191
200
|
parts.push("exec");
|
package/hub/codex-adapter.mjs
CHANGED
|
@@ -118,6 +118,9 @@ export function buildExecArgs(opts = {}) {
|
|
|
118
118
|
const prompt = typeof opts.prompt === "string" ? opts.prompt : "";
|
|
119
119
|
const command = buildExecCommand(prompt, opts.resultFile || null, {
|
|
120
120
|
profile: opts.profile,
|
|
121
|
+
codexHome: opts.codexHome,
|
|
122
|
+
disallowUltra: opts.disallowUltra,
|
|
123
|
+
enforceCanonicalProfile: opts.enforceCanonicalProfile,
|
|
121
124
|
skipGitRepoCheck: true,
|
|
122
125
|
sandboxBypass: true,
|
|
123
126
|
cwd: opts.cwd,
|
package/hub/intent.mjs
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import crypto from "node:crypto";
|
|
6
|
+
import { resolveCodexAgentPolicy } from "../scripts/lib/agent-route-policy.mjs";
|
|
6
7
|
import { whichCommand } from "./platform.mjs";
|
|
7
8
|
|
|
8
9
|
/** 캐시 엔트리: { category, confidence, ts } */
|
|
@@ -61,31 +62,27 @@ function _tryCodexClassify(prompt) {
|
|
|
61
62
|
* triflux 특화 의도 카테고리 (10개)
|
|
62
63
|
*/
|
|
63
64
|
export const INTENT_CATEGORIES = {
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
},
|
|
74
|
-
debug: { agent: "debugger", mcp: "implement", effort: "gpt56_sol_xhigh" },
|
|
75
|
-
analyze: { agent: "analyst", mcp: "analyze", effort: "gpt56_sol_xhigh" },
|
|
76
|
-
design: { agent: "architect", mcp: "analyze", effort: "gpt56_sol_xhigh" },
|
|
77
|
-
review: { agent: "code-reviewer", mcp: "review", effort: "gpt56_terra_high" },
|
|
78
|
-
document: { agent: "writer", mcp: "docs", effort: "pro" },
|
|
79
|
-
research: { agent: "scientist", mcp: "analyze", effort: "gpt56_terra_high" },
|
|
80
|
-
"quick-fix": {
|
|
81
|
-
agent: "build-fixer",
|
|
82
|
-
mcp: "implement",
|
|
83
|
-
effort: "gpt56_luna_low",
|
|
84
|
-
},
|
|
85
|
-
explain: { agent: "writer", mcp: "docs", effort: "flash" },
|
|
86
|
-
test: { agent: "test-engineer", mcp: null, effort: null },
|
|
65
|
+
implement: { agent: "executor", mcp: "implement" },
|
|
66
|
+
debug: { agent: "debugger", mcp: "implement" },
|
|
67
|
+
analyze: { agent: "analyst", mcp: "analyze" },
|
|
68
|
+
design: { agent: "architect", mcp: "analyze" },
|
|
69
|
+
review: { agent: "code-reviewer", mcp: "review" },
|
|
70
|
+
document: { agent: "writer", mcp: "docs" },
|
|
71
|
+
research: { agent: "scientist", mcp: "analyze" },
|
|
72
|
+
"quick-fix": { agent: "build-fixer", mcp: "implement" },
|
|
73
|
+
explain: { agent: "writer", mcp: "docs" },
|
|
74
|
+
test: { agent: "test-engineer", mcp: null },
|
|
87
75
|
};
|
|
88
76
|
|
|
77
|
+
function routingFor(category) {
|
|
78
|
+
const route = INTENT_CATEGORIES[category] || INTENT_CATEGORIES.implement;
|
|
79
|
+
return {
|
|
80
|
+
agent: route.agent,
|
|
81
|
+
mcp: route.mcp,
|
|
82
|
+
effort: resolveCodexAgentPolicy(route.agent).profile,
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
89
86
|
/** @internal 키워드 → 카테고리 매핑 패턴 */
|
|
90
87
|
const KEYWORD_PATTERNS = [
|
|
91
88
|
{
|
|
@@ -267,17 +264,12 @@ export function classifyIntent(prompt) {
|
|
|
267
264
|
// 캐시 확인
|
|
268
265
|
const cached = _getCached(hash);
|
|
269
266
|
if (cached) {
|
|
270
|
-
const routing =
|
|
271
|
-
INTENT_CATEGORIES[cached.category] || INTENT_CATEGORIES.implement;
|
|
267
|
+
const routing = routingFor(cached.category);
|
|
272
268
|
return {
|
|
273
269
|
category: cached.category,
|
|
274
270
|
confidence: cached.confidence,
|
|
275
271
|
reasoning: `cache-hit: ${cached.category} (${cached.confidence.toFixed(2)})`,
|
|
276
|
-
routing
|
|
277
|
-
agent: routing.agent,
|
|
278
|
-
mcp: routing.mcp,
|
|
279
|
-
effort: routing.effort,
|
|
280
|
-
},
|
|
272
|
+
routing,
|
|
281
273
|
};
|
|
282
274
|
}
|
|
283
275
|
|
|
@@ -308,12 +300,12 @@ export function classifyIntent(prompt) {
|
|
|
308
300
|
// 캐시 저장
|
|
309
301
|
_intentCache.set(hash, { category, confidence, ts: Date.now() });
|
|
310
302
|
|
|
311
|
-
const routing =
|
|
303
|
+
const routing = routingFor(category);
|
|
312
304
|
return {
|
|
313
305
|
category,
|
|
314
306
|
confidence,
|
|
315
307
|
reasoning,
|
|
316
|
-
routing
|
|
308
|
+
routing,
|
|
317
309
|
};
|
|
318
310
|
}
|
|
319
311
|
|