@triflux/core 10.51.0 → 10.53.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.
Files changed (61) hide show
  1. package/hub/bridge.mjs +69 -1197
  2. package/hub/cli-adapter-base.mjs +4 -104
  3. package/hub/codex-adapter.mjs +7 -116
  4. package/hub/index.mjs +3 -20
  5. package/hub/lib/process-utils.mjs +1 -33
  6. package/hub/team/claude-daemon-control.mjs +1 -2
  7. package/hub/team/claude-session-projection.mjs +5 -73
  8. package/hub/team/claude-transcript.mjs +19 -0
  9. package/hub/team/nativeProxy.mjs +759 -0
  10. package/hub/team/session-context.mjs +1 -1
  11. package/hud/constants.mjs +9 -22
  12. package/hud/hud-qos-status.mjs +16 -19
  13. package/hud/providers/codex-probe.mjs +2 -31
  14. package/hud/providers/codex.mjs +16 -58
  15. package/hud/providers/gemini.mjs +20 -0
  16. package/hud/renderers.mjs +101 -77
  17. package/hud/utils.mjs +9 -13
  18. package/package.json +3 -6
  19. package/scripts/lib/agent-route-policy.mjs +0 -67
  20. package/scripts/lib/cli-claude.mjs +0 -12
  21. package/scripts/lib/env-probe.mjs +0 -70
  22. package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
  23. package/scripts/lib/mcp-guard-engine.mjs +42 -101
  24. package/scripts/lib/session-presence.mjs +1 -99
  25. package/hub/account-broker.mjs +0 -1221
  26. package/hub/adaptive-diagnostic.mjs +0 -350
  27. package/hub/adaptive-inject.mjs +0 -224
  28. package/hub/adaptive-memory.mjs +0 -277
  29. package/hub/adaptive.mjs +0 -172
  30. package/hub/assign-callbacks.mjs +0 -170
  31. package/hub/delegator/contracts.mjs +0 -38
  32. package/hub/delegator/index.mjs +0 -14
  33. package/hub/delegator/schema/delegator-tools.schema.json +0 -250
  34. package/hub/delegator/service.mjs +0 -336
  35. package/hub/delegator/tool-definitions.mjs +0 -35
  36. package/hub/hitl.mjs +0 -202
  37. package/hub/lib/known-errors.json +0 -72
  38. package/hub/lib/memory-store.mjs +0 -1001
  39. package/hub/lib/phase-manager.mjs +0 -493
  40. package/hub/lib/state-snapshot.mjs +0 -293
  41. package/hub/lib/trace-recorder.mjs +0 -153
  42. package/hub/lib/uuidv7.mjs +0 -45
  43. package/hub/memory-doctor.mjs +0 -640
  44. package/hub/middleware/quota-middleware.mjs +0 -70
  45. package/hub/middleware/request-logger.mjs +0 -191
  46. package/hub/paths.mjs +0 -24
  47. package/hub/pipeline/index.mjs +0 -163
  48. package/hub/pipeline/state.mjs +0 -191
  49. package/hub/pipeline/transitions.mjs +0 -131
  50. package/hub/reflexion.mjs +0 -290
  51. package/hub/role-contract.mjs +0 -312
  52. package/hub/router.mjs +0 -2026
  53. package/hub/session-fingerprint.mjs +0 -418
  54. package/hub/state.mjs +0 -300
  55. package/hub/team/synapse-http.mjs +0 -311
  56. package/hub/team-bridge.mjs +0 -27
  57. package/scripts/lib/claudemd-scanner.mjs +0 -26
  58. package/scripts/lib/context.mjs +0 -51
  59. package/scripts/lib/handoff.mjs +0 -187
  60. package/scripts/lib/logger.mjs +0 -122
  61. package/scripts/lib/stealth-fetch.mjs +0 -176
@@ -1,350 +0,0 @@
1
- import { readFileSync } from "node:fs";
2
- import { dirname, resolve } from "node:path";
3
- import { fileURLToPath } from "node:url";
4
-
5
- import { normalizeError } from "./reflexion.mjs";
6
-
7
- const DEFAULT_KNOWN_ERRORS_PATH = resolve(
8
- dirname(fileURLToPath(import.meta.url)),
9
- "lib/known-errors.json",
10
- );
11
- const DEFAULT_CONFIDENCE = 0.5;
12
- const ADAPTIVE_CONFIDENCE_STEP = 0.1;
13
- const MAX_ADAPTIVE_CONFIDENCE = 0.95;
14
-
15
- function clone(value) {
16
- return value == null ? value : JSON.parse(JSON.stringify(value));
17
- }
18
-
19
- function pickString(...values) {
20
- for (const value of values) {
21
- if (typeof value === "string" && value.trim()) return value.trim();
22
- }
23
- return "";
24
- }
25
-
26
- function pickObject(...values) {
27
- return (
28
- values.find(
29
- (value) => value && typeof value === "object" && !Array.isArray(value),
30
- ) || {}
31
- );
32
- }
33
-
34
- function clampConfidence(value, fallback = DEFAULT_CONFIDENCE) {
35
- const numeric = Number(value);
36
- if (!Number.isFinite(numeric)) return fallback;
37
- return Math.max(0, Math.min(1, numeric));
38
- }
39
-
40
- function normalizeLookup(text) {
41
- return String(text || "")
42
- .trim()
43
- .toLowerCase();
44
- }
45
-
46
- function readPathValue(source, path) {
47
- if (!source || !path) return undefined;
48
- return String(path)
49
- .split(".")
50
- .filter(Boolean)
51
- .reduce((current, key) => current?.[key], source);
52
- }
53
-
54
- function renderTemplate(template, observation, signature) {
55
- if (!template) return "";
56
- const context = pickObject(observation.context);
57
- const dna = pickObject(observation.dna);
58
- const dnaValue = signature.dna_factor
59
- ? (readPathValue(dna, signature.dna_factor) ??
60
- readPathValue(context, signature.dna_factor) ??
61
- readPathValue(observation, signature.dna_factor))
62
- : undefined;
63
- const variables = {
64
- ...context,
65
- ...pickObject(observation.variables),
66
- host: pickString(observation.host, context.host),
67
- value: dnaValue,
68
- };
69
- return String(template).replace(/\{([^}]+)\}/gu, (match, key) => {
70
- const value = variables[key];
71
- return value == null || value === "" ? match : String(value);
72
- });
73
- }
74
-
75
- function buildKnownContextText(observation) {
76
- return normalizeLookup(
77
- [
78
- pickString(observation.contextLabel, observation.context),
79
- pickString(observation.phase),
80
- pickString(observation.step),
81
- ]
82
- .filter(Boolean)
83
- .join(" "),
84
- );
85
- }
86
-
87
- function buildErrorText(observation = {}) {
88
- return [
89
- pickString(observation.error),
90
- pickString(observation.stderr),
91
- pickString(observation.tool_output, observation.output),
92
- pickString(observation.message),
93
- ]
94
- .filter(Boolean)
95
- .join("\n")
96
- .trim();
97
- }
98
-
99
- function normalizeObservation(observation = {}) {
100
- const errorText = buildErrorText(observation);
101
- const projectSlug = pickString(
102
- observation.project_slug,
103
- observation.projectSlug,
104
- observation.context?.project_slug,
105
- observation.context?.projectSlug,
106
- );
107
- return {
108
- ...clone(observation),
109
- errorText,
110
- errorPattern: normalizeError(errorText),
111
- projectSlug,
112
- tool: pickString(observation.tool, observation.tool_name),
113
- contextText: buildKnownContextText(observation),
114
- };
115
- }
116
-
117
- function compileSignatures(raw = {}) {
118
- return Object.entries(raw.signatures || {}).map(([id, signature]) => ({
119
- id,
120
- ...clone(signature),
121
- matcher: new RegExp(String(signature.pattern || ""), "iu"),
122
- }));
123
- }
124
-
125
- export function loadKnownErrors(filePath = DEFAULT_KNOWN_ERRORS_PATH) {
126
- try {
127
- const parsed = JSON.parse(readFileSync(filePath, "utf8"));
128
- return {
129
- path: filePath,
130
- version: parsed.version ?? 1,
131
- signatures: compileSignatures(parsed),
132
- };
133
- } catch {
134
- return { path: filePath, version: 0, signatures: [] };
135
- }
136
- }
137
-
138
- function scoreKnownMatch(signature, observation) {
139
- if (
140
- !observation.errorText ||
141
- !signature.matcher.test(observation.errorText)
142
- ) {
143
- return null;
144
- }
145
- if (
146
- signature.tool &&
147
- observation.tool &&
148
- normalizeLookup(signature.tool) !== normalizeLookup(observation.tool)
149
- ) {
150
- return null;
151
- }
152
- if (
153
- signature.context &&
154
- observation.contextText &&
155
- !observation.contextText.includes(normalizeLookup(signature.context))
156
- ) {
157
- return null;
158
- }
159
- return clampConfidence(
160
- Number(signature.confidence_base ?? DEFAULT_CONFIDENCE) +
161
- (signature.tool && observation.tool ? 0.02 : 0) +
162
- (signature.context && observation.contextText ? 0.02 : 0) +
163
- (signature.dna_factor ? 0.01 : 0),
164
- );
165
- }
166
-
167
- function severityFromConfidence(confidence, fallback = "medium") {
168
- if (confidence >= 0.9) return "critical";
169
- if (confidence >= 0.75) return "high";
170
- if (confidence >= 0.55) return "medium";
171
- return fallback;
172
- }
173
-
174
- export function matchKnownError(catalog, observationInput = {}) {
175
- const observation = normalizeObservation(observationInput);
176
- const matched = (catalog?.signatures || [])
177
- .map((signature) => {
178
- const confidence = scoreKnownMatch(signature, observation);
179
- return confidence == null ? null : { signature, confidence };
180
- })
181
- .filter(Boolean)
182
- .sort((left, right) => right.confidence - left.confidence)[0];
183
-
184
- if (!matched) return null;
185
- const { signature, confidence } = matched;
186
- return {
187
- matched: true,
188
- source: "known",
189
- signature_id: signature.id,
190
- project_slug: observation.projectSlug,
191
- error_pattern: observation.errorPattern,
192
- error_message: observation.errorText,
193
- confidence,
194
- severity: signature.severity || severityFromConfidence(confidence),
195
- tool: signature.tool || observation.tool,
196
- context: signature.context || observation.contextText || null,
197
- root_cause: signature.root_cause || "known failure pattern",
198
- rule: renderTemplate(signature.rule_template, observation, signature),
199
- fix: signature.fix || null,
200
- dna_factor: signature.dna_factor || null,
201
- };
202
- }
203
-
204
- function resolveRuleStore(options = {}) {
205
- return options.store || options.adaptiveMemory || null;
206
- }
207
-
208
- function ensureAdaptiveRule(store, observation) {
209
- if (
210
- !store?.findAdaptiveRule ||
211
- !store?.addAdaptiveRule ||
212
- !observation.projectSlug
213
- ) {
214
- return null;
215
- }
216
- const identity = {
217
- project_slug: observation.projectSlug,
218
- pattern: observation.errorPattern,
219
- };
220
- const current = store.findAdaptiveRule(
221
- identity.project_slug,
222
- identity.pattern,
223
- );
224
- if (!current) {
225
- return store.addAdaptiveRule(identity);
226
- }
227
- if (!store.updateRuleConfidence) return current;
228
- return store.updateRuleConfidence(
229
- identity.project_slug,
230
- identity.pattern,
231
- Math.min(
232
- MAX_ADAPTIVE_CONFIDENCE,
233
- current.confidence + ADAPTIVE_CONFIDENCE_STEP,
234
- ),
235
- { hit_count_increment: 1 },
236
- );
237
- }
238
-
239
- function buildAdaptiveDiagnosis(rule, observation) {
240
- if (!rule) {
241
- return {
242
- matched: false,
243
- source: "novel",
244
- project_slug: observation.projectSlug,
245
- error_pattern: observation.errorPattern,
246
- error_message: observation.errorText,
247
- confidence: DEFAULT_CONFIDENCE,
248
- severity: "low",
249
- root_cause: "새로운 실패 패턴으로 분류됨",
250
- rule: "",
251
- fix: null,
252
- };
253
- }
254
- const matched =
255
- Number(rule.hit_count || 0) > 1 ||
256
- Number(rule.confidence || 0) > DEFAULT_CONFIDENCE;
257
- const confidence = clampConfidence(rule.confidence, DEFAULT_CONFIDENCE);
258
- return {
259
- matched,
260
- source: matched ? "adaptive" : "novel",
261
- project_slug: rule.project_slug,
262
- error_pattern: rule.pattern,
263
- error_message: observation.errorText,
264
- confidence,
265
- severity: severityFromConfidence(confidence, matched ? "medium" : "low"),
266
- root_cause: matched
267
- ? "반복 관측된 adaptive rule과 일치"
268
- : "adaptive memory에 첫 관측으로 저장됨",
269
- rule: matched
270
- ? `프로젝트 ${rule.project_slug}에서 동일 패턴이 ${rule.hit_count}회 관측되었습니다.`
271
- : `프로젝트 ${rule.project_slug}의 adaptive memory에 패턴을 기록했습니다.`,
272
- fix: matched
273
- ? "최근 성공한 수정/회피 전략을 재적용하세요."
274
- : "추가 관측 후 adaptive rule을 승격하세요.",
275
- adaptive_rule: clone(rule),
276
- };
277
- }
278
-
279
- function createHealthyState(catalog) {
280
- return {
281
- state: "healthy",
282
- known_errors_count: catalog.signatures.length,
283
- last_error: null,
284
- };
285
- }
286
-
287
- function createDegradedState(error) {
288
- return {
289
- state: "degraded",
290
- known_errors_count: 0,
291
- last_error: {
292
- name: error?.name || "Error",
293
- message: error?.message || "unknown adaptive diagnostic error",
294
- },
295
- };
296
- }
297
-
298
- export function createDiagnosticPipeline(options = {}) {
299
- const store = resolveRuleStore(options);
300
- let catalog = options.knownErrors
301
- ? { signatures: compileSignatures({ signatures: options.knownErrors }) }
302
- : null;
303
- let health = catalog ? createHealthyState(catalog) : null;
304
-
305
- function ensureCatalog() {
306
- if (catalog) return catalog;
307
- try {
308
- catalog = loadKnownErrors(
309
- options.knownErrorsPath || DEFAULT_KNOWN_ERRORS_PATH,
310
- );
311
- health = createHealthyState(catalog);
312
- } catch (error) {
313
- catalog = { signatures: [] };
314
- health = createDegradedState(error);
315
- }
316
- return catalog;
317
- }
318
-
319
- function diagnoseFailure(observationInput = {}) {
320
- const observation = normalizeObservation(observationInput);
321
- const nextCatalog = ensureCatalog();
322
- const known = matchKnownError(nextCatalog, observation);
323
- if (known) return known;
324
- const adaptiveRule = observation.errorPattern
325
- ? ensureAdaptiveRule(store, observation)
326
- : null;
327
- return buildAdaptiveDiagnosis(adaptiveRule, observation);
328
- }
329
-
330
- function getHealth() {
331
- return clone(health || (ensureCatalog() && health));
332
- }
333
-
334
- function listKnownErrors() {
335
- return (ensureCatalog().signatures || []).map(({ matcher, ...signature }) =>
336
- clone(signature),
337
- );
338
- }
339
-
340
- return Object.freeze({
341
- diagnose: diagnoseFailure,
342
- diagnoseFailure,
343
- run: diagnoseFailure,
344
- getHealth,
345
- listKnownErrors,
346
- });
347
- }
348
-
349
- export { DEFAULT_KNOWN_ERRORS_PATH };
350
- export default createDiagnosticPipeline;
@@ -1,224 +0,0 @@
1
- import { existsSync, readFileSync, writeFileSync } from "node:fs";
2
- import { join, resolve } from "node:path";
3
-
4
- const SECTION_HEADING = "## Adaptive Rules (triflux auto-generated)";
5
- const DEFAULT_MAX_RULES = 10;
6
- const SECTION_RE = /^## Adaptive Rules \(triflux auto-generated\)$/mu;
7
- const BLOCK_RE =
8
- /<!-- tfx-adaptive:start rule_id="([^"]+)" confidence=([0-9.]+) occurrences=(\d+) first_seen=([0-9-]+) last_seen=([0-9-]+) -->\r?\n([^\r\n]*)\r?\n<!-- tfx-adaptive:end -->/gu;
9
-
10
- function cloneRule(rule) {
11
- return Object.freeze({ ...rule });
12
- }
13
-
14
- function clampConfidence(value) {
15
- const numeric = Number(value);
16
- if (!Number.isFinite(numeric)) return 0;
17
- return Math.min(1, Math.max(0, numeric));
18
- }
19
-
20
- function normalizeOccurrences(value) {
21
- const numeric = Number(value);
22
- if (!Number.isFinite(numeric)) return 1;
23
- return Math.max(1, Math.trunc(numeric));
24
- }
25
-
26
- function formatConfidence(value) {
27
- return Number(clampConfidence(value).toFixed(6)).toString();
28
- }
29
-
30
- function normalizeDate(value, fallback) {
31
- const text = String(value ?? fallback ?? "").trim();
32
- return text || fallback;
33
- }
34
-
35
- function normalizeRuleInput(rule, fallback = {}) {
36
- if (!rule || typeof rule !== "object") return null;
37
-
38
- const id = String(rule.id ?? rule.rule_id ?? fallback.id ?? "").trim();
39
- const text = String(rule.rule ?? rule.text ?? fallback.rule ?? "").trim();
40
- const firstSeen = normalizeDate(
41
- rule.firstSeen ?? rule.first_seen,
42
- fallback.firstSeen ?? fallback.lastSeen ?? "1970-01-01",
43
- );
44
- const lastSeen = normalizeDate(
45
- rule.lastSeen ?? rule.last_seen,
46
- fallback.lastSeen ?? firstSeen,
47
- );
48
- if (!id || !text || /["\r\n]/u.test(id) || /[\r\n]/u.test(text)) {
49
- return null;
50
- }
51
-
52
- return cloneRule({
53
- id,
54
- rule: text,
55
- confidence: clampConfidence(rule.confidence ?? fallback.confidence),
56
- occurrences: normalizeOccurrences(rule.occurrences ?? fallback.occurrences),
57
- firstSeen,
58
- lastSeen,
59
- });
60
- }
61
-
62
- function trimLeadingBlankLines(text) {
63
- return String(text ?? "").replace(/^(?:[ \t]*\r?\n)+/u, "");
64
- }
65
-
66
- function trimTrailingBlankLines(text) {
67
- return String(text ?? "").replace(/(?:\r?\n[ \t]*)+$/u, "");
68
- }
69
-
70
- function parseInjectedRules(sectionBody = "") {
71
- const matches = Array.from(String(sectionBody).matchAll(BLOCK_RE));
72
- return matches.map(
73
- ([, id, confidence, occurrences, firstSeen, lastSeen, text]) =>
74
- cloneRule({
75
- id,
76
- rule: text,
77
- confidence: clampConfidence(confidence),
78
- occurrences: normalizeOccurrences(occurrences),
79
- firstSeen,
80
- lastSeen,
81
- }),
82
- );
83
- }
84
-
85
- function readDocument(claudeMdPath) {
86
- const raw = existsSync(claudeMdPath)
87
- ? readFileSync(claudeMdPath, "utf8")
88
- : "";
89
- const sectionStart = raw.search(SECTION_RE);
90
- if (sectionStart === -1) {
91
- return { before: raw, after: "", rules: [] };
92
- }
93
-
94
- const headingEnd = raw.indexOf("\n", sectionStart);
95
- const bodyStart = headingEnd === -1 ? raw.length : headingEnd + 1;
96
- const rest = raw.slice(bodyStart);
97
- const nextHeadingOffset = rest.search(/^#{1,6}\s/mu);
98
- const sectionEnd =
99
- nextHeadingOffset === -1 ? raw.length : bodyStart + nextHeadingOffset;
100
- const body = raw.slice(bodyStart, sectionEnd);
101
-
102
- return {
103
- before: raw.slice(0, sectionStart),
104
- after: raw.slice(sectionEnd),
105
- rules: parseInjectedRules(body),
106
- };
107
- }
108
-
109
- function serializeRule(rule) {
110
- return [
111
- `<!-- tfx-adaptive:start rule_id="${rule.id}" confidence=${formatConfidence(rule.confidence)} occurrences=${rule.occurrences} first_seen=${rule.firstSeen} last_seen=${rule.lastSeen} -->`,
112
- rule.rule,
113
- "<!-- tfx-adaptive:end -->",
114
- ].join("\n");
115
- }
116
-
117
- function serializeDocument(before, rules, after) {
118
- const section =
119
- rules.length > 0
120
- ? `${SECTION_HEADING}\n\n${rules.map(serializeRule).join("\n\n")}`
121
- : "";
122
- const parts = [
123
- trimTrailingBlankLines(before),
124
- section,
125
- trimLeadingBlankLines(after),
126
- ].filter(Boolean);
127
- return parts.length > 0 ? `${parts.join("\n\n")}\n` : "";
128
- }
129
-
130
- function enforceMaxRules(rules, maxRules) {
131
- if (rules.length <= maxRules) return rules.map(cloneRule);
132
- const ranked = rules
133
- .map((rule, index) => ({ ...rule, index }))
134
- .sort(
135
- (left, right) =>
136
- left.confidence - right.confidence ||
137
- left.occurrences - right.occurrences ||
138
- left.lastSeen.localeCompare(right.lastSeen) ||
139
- left.index - right.index ||
140
- left.id.localeCompare(right.id),
141
- );
142
- const removedIds = new Set(
143
- ranked.slice(0, rules.length - maxRules).map((rule) => rule.id),
144
- );
145
- return rules.filter((rule) => !removedIds.has(rule.id)).map(cloneRule);
146
- }
147
-
148
- export function createAdaptiveInjector(opts = {}) {
149
- const claudeMdPath = resolve(
150
- opts.claudeMdPath ?? join(process.cwd(), "CLAUDE.md"),
151
- );
152
- const maxRules =
153
- Number.isInteger(opts.maxRules) && opts.maxRules > 0
154
- ? opts.maxRules
155
- : DEFAULT_MAX_RULES;
156
-
157
- function listInjected() {
158
- return readDocument(claudeMdPath).rules.map(cloneRule);
159
- }
160
-
161
- function inject(rule) {
162
- const document = readDocument(claudeMdPath);
163
- const targetId = String(rule?.id ?? rule?.rule_id ?? "").trim();
164
- const existing = document.rules.find((item) => item.id === targetId);
165
- const normalized = normalizeRuleInput(rule, existing ?? {});
166
- if (!normalized) return false;
167
-
168
- const nextRules = existing
169
- ? document.rules.map((item) =>
170
- item.id === normalized.id
171
- ? cloneRule({
172
- ...item,
173
- confidence: normalized.confidence,
174
- occurrences: normalized.occurrences,
175
- lastSeen: normalized.lastSeen,
176
- })
177
- : cloneRule(item),
178
- )
179
- : [...document.rules.map(cloneRule), normalized];
180
- const limitedRules = enforceMaxRules(nextRules, maxRules);
181
- writeFileSync(
182
- claudeMdPath,
183
- serializeDocument(document.before, limitedRules, document.after),
184
- "utf8",
185
- );
186
- return limitedRules.some((item) => item.id === normalized.id);
187
- }
188
-
189
- function remove(ruleId) {
190
- const targetId = String(ruleId ?? "").trim();
191
- if (!targetId || !existsSync(claudeMdPath)) return false;
192
- const document = readDocument(claudeMdPath);
193
- if (!document.rules.some((rule) => rule.id === targetId)) return false;
194
- const nextRules = document.rules
195
- .filter((rule) => rule.id !== targetId)
196
- .map(cloneRule);
197
- writeFileSync(
198
- claudeMdPath,
199
- serializeDocument(document.before, nextRules, document.after),
200
- "utf8",
201
- );
202
- return true;
203
- }
204
-
205
- function cleanup(activeRuleIds = []) {
206
- const activeIds = new Set(
207
- Array.isArray(activeRuleIds) ? activeRuleIds : Array.from(activeRuleIds),
208
- );
209
- return listInjected().reduce(
210
- (count, rule) =>
211
- count + (activeIds.has(rule.id) ? 0 : Number(remove(rule.id))),
212
- 0,
213
- );
214
- }
215
-
216
- return Object.freeze({
217
- inject,
218
- remove,
219
- listInjected,
220
- cleanup,
221
- });
222
- }
223
-
224
- export default createAdaptiveInjector;