triflux 10.3.4 → 10.7.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/LICENSE +21 -21
- package/bin/tfx-doctor-tui.mjs +1 -1
- package/bin/tfx-doctor.mjs +6 -1
- package/bin/tfx-profile.mjs +1 -1
- package/bin/tfx-setup-tui.mjs +1 -1
- package/bin/tfx-setup.mjs +6 -1
- package/bin/triflux.mjs +2396 -1140
- package/hooks/agent-route-guard.mjs +12 -8
- package/hooks/cross-review-tracker.mjs +21 -8
- package/hooks/error-context.mjs +19 -7
- package/hooks/hook-adaptive-collector.mjs +18 -16
- package/hooks/hook-manager.mjs +93 -32
- package/hooks/hook-orchestrator.mjs +108 -24
- package/hooks/hook-registry.json +11 -0
- package/hooks/keyword-rules.json +6 -10
- package/hooks/lib/resolve-root.mjs +1 -1
- package/hooks/mcp-config-watcher.mjs +6 -2
- package/hooks/pipeline-stop.mjs +3 -6
- package/hooks/safety-guard.mjs +99 -28
- package/hooks/session-start-fast.mjs +143 -0
- package/hooks/subagent-verifier.mjs +5 -4
- package/hub/account-broker.mjs +256 -60
- package/hub/adaptive-diagnostic.mjs +75 -48
- package/hub/adaptive-inject.mjs +95 -57
- package/hub/adaptive-memory.mjs +156 -42
- package/hub/adaptive.mjs +60 -31
- package/hub/assign-callbacks.mjs +67 -30
- package/hub/bridge.mjs +0 -1
- package/hub/cli-adapter-base.mjs +200 -48
- package/hub/codex-adapter.mjs +76 -96
- package/hub/codex-compat.mjs +3 -3
- package/hub/codex-preflight.mjs +63 -37
- package/hub/delegator/contracts.mjs +19 -23
- package/hub/delegator/index.mjs +3 -3
- package/hub/delegator/service.mjs +88 -64
- package/hub/delegator/tool-definitions.mjs +5 -5
- package/hub/fullcycle.mjs +33 -17
- package/hub/gemini-adapter.mjs +69 -94
- package/hub/hitl.mjs +89 -30
- package/hub/intent.mjs +161 -38
- package/hub/lib/cache-guard.mjs +43 -17
- package/hub/lib/mcp-response-cache.mjs +66 -32
- package/hub/lib/memory-store.mjs +285 -111
- package/hub/lib/path-utils.mjs +35 -37
- package/hub/lib/process-utils.mjs +106 -37
- package/hub/lib/spawn-trace.mjs +527 -0
- package/hub/lib/ssh-command.mjs +34 -4
- package/hub/lib/ssh-retry.mjs +5 -1
- package/hub/lib/uuidv7.mjs +4 -3
- package/hub/memory-doctor.mjs +266 -106
- package/hub/middleware/request-logger.mjs +61 -34
- package/hub/paths.mjs +9 -9
- package/hub/pipeline/gates/confidence.mjs +34 -15
- package/hub/pipeline/gates/consensus.mjs +27 -15
- package/hub/pipeline/gates/index.mjs +7 -3
- package/hub/pipeline/gates/selfcheck.mjs +57 -19
- package/hub/pipeline/index.mjs +77 -42
- package/hub/pipeline/state.mjs +10 -10
- package/hub/pipeline/transitions.mjs +40 -23
- package/hub/platform.mjs +57 -48
- package/hub/promote-penalties.mjs +25 -7
- package/hub/quality/deslop.mjs +70 -49
- package/hub/research.mjs +32 -25
- package/hub/router.mjs +240 -107
- package/hub/routing/complexity.mjs +132 -29
- package/hub/routing/index.mjs +17 -12
- package/hub/routing/q-learning.mjs +76 -28
- package/hub/server.mjs +4 -4
- package/hub/session-fingerprint.mjs +126 -60
- package/hub/state.mjs +84 -43
- package/hub/store-adapter.mjs +59 -26
- package/hub/store.mjs +356 -153
- package/hub/team/agent-map.json +22 -7
- package/hub/team/ansi.mjs +186 -122
- package/hub/team/backend.mjs +28 -10
- package/hub/team/cli/commands/attach.mjs +29 -9
- package/hub/team/cli/commands/control.mjs +29 -8
- package/hub/team/cli/commands/debug.mjs +32 -11
- package/hub/team/cli/commands/focus.mjs +38 -11
- package/hub/team/cli/commands/interrupt.mjs +18 -6
- package/hub/team/cli/commands/kill.mjs +16 -5
- package/hub/team/cli/commands/list.mjs +11 -4
- package/hub/team/cli/commands/send.mjs +19 -6
- package/hub/team/cli/commands/start/index.mjs +154 -31
- package/hub/team/cli/commands/start/parse-args.mjs +38 -11
- package/hub/team/cli/commands/start/start-headless.mjs +112 -36
- package/hub/team/cli/commands/start/start-in-process.mjs +12 -2
- package/hub/team/cli/commands/start/start-mux.mjs +70 -21
- package/hub/team/cli/commands/start/start-wt.mjs +29 -12
- package/hub/team/cli/commands/status.mjs +43 -14
- package/hub/team/cli/commands/stop.mjs +11 -4
- package/hub/team/cli/commands/task.mjs +8 -3
- package/hub/team/cli/commands/tasks.mjs +1 -1
- package/hub/team/cli/index.mjs +2 -2
- package/hub/team/cli/manifest.mjs +38 -8
- package/hub/team/cli/render.mjs +30 -8
- package/hub/team/cli/services/attach-fallback.mjs +31 -11
- package/hub/team/cli/services/hub-client.mjs +42 -14
- package/hub/team/cli/services/member-selector.mjs +11 -4
- package/hub/team/cli/services/native-control.mjs +48 -21
- package/hub/team/cli/services/runtime-mode.mjs +2 -1
- package/hub/team/cli/services/state-store.mjs +25 -8
- package/hub/team/cli/services/task-model.mjs +16 -6
- package/hub/team/conductor-mesh-bridge.mjs +24 -23
- package/hub/team/conductor.mjs +8 -4
- package/hub/team/dashboard-anchor.mjs +4 -5
- package/hub/team/dashboard-layout.mjs +3 -1
- package/hub/team/dashboard-open.mjs +41 -21
- package/hub/team/dashboard.mjs +76 -28
- package/hub/team/event-log.mjs +18 -10
- package/hub/team/handoff.mjs +31 -15
- package/hub/team/headless.mjs +2 -1
- package/hub/team/health-probe.mjs +69 -54
- package/hub/team/launcher-template.mjs +16 -13
- package/hub/team/native-supervisor.mjs +65 -21
- package/hub/team/native.mjs +74 -35
- package/hub/team/nativeProxy.mjs +184 -113
- package/hub/team/notify.mjs +119 -76
- package/hub/team/orchestrator.mjs +9 -4
- package/hub/team/pane.mjs +12 -7
- package/hub/team/process-cleanup.mjs +25 -16
- package/hub/team/psmux.mjs +491 -201
- package/hub/team/remote-probe.mjs +68 -52
- package/hub/team/remote-session.mjs +117 -59
- package/hub/team/remote-watcher.mjs +61 -33
- package/hub/team/routing.mjs +51 -25
- package/hub/team/runtime-strategy.mjs +3 -1
- package/hub/team/session.mjs +98 -34
- package/hub/team/staleState.mjs +72 -30
- package/hub/team/swarm-locks.mjs +15 -13
- package/hub/team/swarm-planner.mjs +32 -21
- package/hub/team/swarm-reconciler.mjs +48 -23
- package/hub/team/tui-lite.mjs +266 -68
- package/hub/team/tui-remote-adapter.mjs +14 -10
- package/hub/team/tui-viewer.mjs +99 -43
- package/hub/team/tui.mjs +708 -271
- package/hub/team/worktree-lifecycle.mjs +152 -58
- package/hub/team/wt-manager.mjs +24 -14
- package/hub/token-mode.mjs +71 -71
- package/hub/tray.mjs +66 -23
- package/hub/workers/claude-worker.mjs +162 -118
- package/hub/workers/codex-mcp.mjs +192 -141
- package/hub/workers/delegator-mcp.mjs +507 -333
- package/hub/workers/factory.mjs +8 -8
- package/hub/workers/gemini-worker.mjs +115 -84
- package/hub/workers/interface.mjs +6 -1
- package/hub/workers/worker-utils.mjs +21 -14
- package/hud/colors.mjs +27 -9
- package/hud/constants.mjs +162 -26
- package/hud/context-monitor.mjs +82 -41
- package/hud/hud-qos-status.mjs +129 -49
- package/hud/mission-board.mjs +6 -3
- package/hud/providers/claude.mjs +226 -115
- package/hud/providers/codex.mjs +62 -22
- package/hud/providers/gemini.mjs +168 -56
- package/hud/renderers.mjs +384 -119
- package/hud/terminal.mjs +101 -31
- package/hud/utils.mjs +78 -38
- package/mesh/index.mjs +11 -5
- package/mesh/mesh-budget.mjs +18 -9
- package/mesh/mesh-heartbeat.mjs +1 -1
- package/mesh/mesh-queue.mjs +3 -5
- package/mesh/mesh-router.mjs +5 -4
- package/package.json +2 -1
- package/scripts/__tests__/gen-skill-docs.test.mjs +36 -7
- package/scripts/__tests__/keyword-detector.test.mjs +77 -28
- package/scripts/__tests__/mcp-guard-engine.test.mjs +58 -20
- package/scripts/__tests__/remote-spawn-transfer.test.mjs +30 -19
- package/scripts/__tests__/remote-spawn.test.mjs +10 -4
- package/scripts/__tests__/session-start-fast.test.mjs +36 -0
- package/scripts/__tests__/skill-template.test.mjs +98 -50
- package/scripts/__tests__/smoke.test.mjs +1 -1
- package/scripts/__tests__/spawn-trace.test.mjs +102 -0
- package/scripts/__tests__/tfx-doctor-diagnose.test.mjs +48 -0
- package/scripts/cache-doctor.mjs +11 -4
- package/scripts/cache-warmup.mjs +96 -37
- package/scripts/claudemd-sync.mjs +27 -17
- package/scripts/codex-gateway-preflight.mjs +52 -37
- package/scripts/codex-mcp-gateway-sync.mjs +59 -39
- package/scripts/completions/tfx.bash +47 -47
- package/scripts/completions/tfx.fish +44 -44
- package/scripts/completions/tfx.zsh +83 -83
- package/scripts/config-audit.mjs +232 -0
- package/scripts/convert-to-tmpl.mjs +54 -0
- package/scripts/cross-review-gate.mjs +35 -12
- package/scripts/cross-review-tracker.mjs +21 -8
- package/scripts/demo.mjs +35 -17
- package/scripts/doctor-diagnose.mjs +284 -0
- package/scripts/gen-skill-docs.mjs +7 -2
- package/scripts/gen-skill-manifest.mjs +2 -1
- package/scripts/headless-guard.mjs +86 -48
- package/scripts/hub-ensure.mjs +45 -26
- package/scripts/keyword-detector.mjs +41 -20
- package/scripts/keyword-rules-expander.mjs +47 -30
- package/scripts/lib/claudemd-scanner.mjs +6 -1
- package/scripts/lib/context.mjs +3 -3
- package/scripts/lib/cross-review-utils.mjs +6 -3
- package/scripts/lib/env-probe.mjs +47 -28
- package/scripts/lib/gemini-profiles.mjs +44 -10
- package/scripts/lib/handoff.mjs +33 -17
- package/scripts/lib/hook-utils.mjs +8 -6
- package/scripts/lib/keyword-rules.mjs +43 -19
- package/scripts/lib/logger.mjs +24 -24
- package/scripts/lib/mcp-filter.mjs +377 -239
- package/scripts/lib/mcp-guard-engine.mjs +194 -79
- package/scripts/lib/mcp-manifest.mjs +23 -13
- package/scripts/lib/mcp-server-catalog.mjs +300 -63
- package/scripts/lib/psmux-info.mjs +11 -6
- package/scripts/lib/remote-spawn-transfer.mjs +44 -14
- package/scripts/lib/skill-template.mjs +30 -7
- package/scripts/mcp-check.mjs +58 -39
- package/scripts/mcp-gateway-config.mjs +83 -39
- package/scripts/mcp-gateway-ensure.mjs +43 -35
- package/scripts/mcp-gateway-integration-test.mjs +70 -58
- package/scripts/mcp-gateway-start.mjs +126 -60
- package/scripts/mcp-gateway-verify.mjs +24 -22
- package/scripts/mcp-safety-guard.mjs +44 -11
- package/scripts/notion-read.mjs +199 -84
- package/scripts/pack.mjs +94 -89
- package/scripts/preflight-cache.mjs +27 -10
- package/scripts/preinstall.mjs +42 -13
- package/scripts/remote-spawn.mjs +309 -94
- package/scripts/run.cjs +8 -5
- package/scripts/session-spawn-helper.mjs +130 -39
- package/scripts/session-stale-cleanup.mjs +123 -0
- package/scripts/setup.mjs +941 -492
- package/scripts/test-lock.mjs +20 -7
- package/scripts/test-tfx-route-no-claude-native.mjs +16 -12
- package/scripts/tfx-batch-stats.mjs +32 -11
- package/scripts/tfx-gate-activate.mjs +11 -4
- package/scripts/tfx-route-post.mjs +87 -20
- package/scripts/tfx-route-worker.mjs +57 -51
- package/scripts/tfx-route.sh +41 -124
- package/scripts/tmp-cleanup.mjs +21 -7
- package/scripts/token-snapshot.mjs +204 -85
- package/skills/.omc/state/agent-replay-8f0e10a9-9693-4410-96f5-a6b07e8ed995.jsonl +1 -0
- package/skills/.omc/state/idle-notif-cooldown.json +3 -0
- package/skills/.omc/state/last-tool-error.json +7 -0
- package/skills/.omc/state/subagent-tracking.json +7 -0
- package/skills/_templates/base.md +1 -6
- package/skills/merge-worktree/SKILL.md.tmpl +144 -0
- package/skills/shared/telemetry-segment.md +6 -0
- package/skills/star-prompt/SKILL.md.tmpl +222 -0
- package/skills/tfx-analysis/SKILL.md.tmpl +107 -0
- package/skills/tfx-analysis/skill.json +1 -6
- package/skills/tfx-auto/SKILL.md +1 -0
- package/skills/tfx-auto-codex/SKILL.md.tmpl +106 -0
- package/skills/tfx-auto-codex/skill.json +1 -3
- package/skills/tfx-autopilot/SKILL.md.tmpl +116 -0
- package/skills/tfx-autopilot/skill.json +1 -5
- package/skills/tfx-autoresearch/SKILL.md.tmpl +136 -0
- package/skills/tfx-autoroute/SKILL.md.tmpl +189 -0
- package/skills/tfx-autoroute/skill.json +1 -7
- package/skills/tfx-codex/SKILL.md +1 -0
- package/skills/tfx-codex/skill.json +1 -3
- package/skills/tfx-codex-swarm/SKILL.md.tmpl +16 -0
- package/skills/tfx-codex-swarm/evals/evals.json +1 -1
- package/skills/tfx-codex-swarm/skill.json +1 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/benchmark.json +54 -12
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/with_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/full-swarm-all-prds/without_skill/grading.json +35 -7
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/with_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/implicit-swarm-no-keywords/without_skill/grading.json +25 -5
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/with_skill/grading.json +20 -4
- package/skills/tfx-codex-swarm-workspace/iteration-1/selective-spawn-with-override/without_skill/grading.json +16 -4
- package/skills/tfx-consensus/SKILL.md.tmpl +146 -0
- package/skills/tfx-debate/SKILL.md.tmpl +192 -0
- package/skills/tfx-debate/skill.json +1 -7
- package/skills/tfx-deep-analysis/SKILL.md.tmpl +228 -0
- package/skills/tfx-deep-analysis/skill.json +1 -5
- package/skills/tfx-deep-interview/SKILL.md.tmpl +203 -0
- package/skills/tfx-deep-plan/SKILL.md.tmpl +282 -0
- package/skills/tfx-deep-qa/SKILL.md.tmpl +165 -0
- package/skills/tfx-deep-qa/skill.json +1 -6
- package/skills/tfx-deep-research/SKILL.md.tmpl +217 -0
- package/skills/tfx-deep-review/SKILL.md.tmpl +179 -0
- package/skills/tfx-doctor/SKILL.md +21 -0
- package/skills/tfx-doctor/SKILL.md.tmpl +172 -0
- package/skills/tfx-doctor/skill.json +1 -3
- package/skills/tfx-find/SKILL.md +1 -0
- package/skills/tfx-forge/SKILL.md.tmpl +187 -0
- package/skills/tfx-fullcycle/SKILL.md.tmpl +286 -0
- package/skills/tfx-fullcycle/skill.json +1 -6
- package/skills/tfx-gemini/SKILL.md.tmpl +91 -0
- package/skills/tfx-gemini/skill.json +1 -3
- package/skills/tfx-hooks/SKILL.md.tmpl +216 -0
- package/skills/tfx-hooks/skill.json +1 -3
- package/skills/tfx-hub/SKILL.md.tmpl +212 -0
- package/skills/tfx-hub/skill.json +1 -3
- package/skills/tfx-index/SKILL.md +1 -0
- package/skills/tfx-index/skill.json +1 -6
- package/skills/tfx-interview/SKILL.md.tmpl +285 -0
- package/skills/tfx-multi/SKILL.md.tmpl +183 -0
- package/skills/tfx-multi/skill.json +1 -3
- package/skills/tfx-panel/SKILL.md.tmpl +189 -0
- package/skills/tfx-panel/skill.json +1 -7
- package/skills/tfx-persist/SKILL.md.tmpl +270 -0
- package/skills/tfx-persist/skill.json +1 -7
- package/skills/tfx-plan/SKILL.md +1 -0
- package/skills/tfx-plan/skill.json +1 -6
- package/skills/tfx-profile/SKILL.md.tmpl +239 -0
- package/skills/tfx-profile/skill.json +1 -3
- package/skills/tfx-prune/SKILL.md.tmpl +200 -0
- package/skills/tfx-prune/skill.json +1 -7
- package/skills/tfx-psmux-rules/SKILL.md.tmpl +326 -0
- package/skills/tfx-psmux-rules/skill.json +1 -4
- package/skills/tfx-qa/SKILL.md +1 -0
- package/skills/tfx-qa/skill.json +1 -6
- package/skills/tfx-ralph/SKILL.md.tmpl +28 -0
- package/skills/tfx-ralph/skill.json +1 -4
- package/skills/tfx-remote-setup/SKILL.md.tmpl +576 -0
- package/skills/tfx-remote-setup/skill.json +1 -3
- package/skills/tfx-remote-spawn/SKILL.md.tmpl +263 -0
- package/skills/tfx-remote-spawn/references/hosts.json +16 -0
- package/skills/tfx-remote-spawn/skill.json +1 -4
- package/skills/tfx-research/SKILL.md +1 -0
- package/skills/tfx-review/SKILL.md +1 -0
- package/skills/tfx-review/skill.json +1 -6
- package/skills/tfx-setup/SKILL.md.tmpl +504 -0
- package/skills/tfx-setup/skill.json +1 -3
- package/skills/tfx-swarm/SKILL.md +22 -0
- package/skills/tfx-swarm/SKILL.md.tmpl +218 -0
- package/tui/codex-profile.mjs +88 -33
- package/tui/core.mjs +45 -15
- package/tui/doctor.mjs +75 -28
- package/tui/gemini-profile.mjs +74 -29
- package/tui/monitor-data.mjs +8 -4
- package/tui/monitor.mjs +71 -27
- package/tui/setup.mjs +133 -42
package/hub/adaptive-memory.mjs
CHANGED
|
@@ -1,8 +1,14 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
import {
|
|
2
|
+
existsSync,
|
|
3
|
+
mkdirSync,
|
|
4
|
+
readFileSync,
|
|
5
|
+
rmSync,
|
|
6
|
+
writeFileSync,
|
|
7
|
+
} from "node:fs";
|
|
8
|
+
import { homedir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
4
10
|
|
|
5
|
-
const SESSION_FILE =
|
|
11
|
+
const SESSION_FILE = "adaptive-session.json";
|
|
6
12
|
const DEFAULT_CONFIDENCE = 0.5;
|
|
7
13
|
const TIER2_DECAY_STEP = 0.2;
|
|
8
14
|
const TIER2_DECAY_INTERVAL = 5;
|
|
@@ -11,24 +17,67 @@ const TIER3_WARN_THRESHOLD = 10;
|
|
|
11
17
|
const TIER3_REMOVE_THRESHOLD = 20;
|
|
12
18
|
|
|
13
19
|
const clone = (v) => (v == null ? v : JSON.parse(JSON.stringify(v)));
|
|
14
|
-
const clamp01 = (v) => {
|
|
15
|
-
const
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
const
|
|
21
|
-
const
|
|
22
|
-
|
|
20
|
+
const clamp01 = (v) => {
|
|
21
|
+
const n = Number(v);
|
|
22
|
+
return Number.isFinite(n)
|
|
23
|
+
? Number(Math.max(0, Math.min(1, n)).toFixed(4))
|
|
24
|
+
: DEFAULT_CONFIDENCE;
|
|
25
|
+
};
|
|
26
|
+
const toDate = (v = Date.now()) => {
|
|
27
|
+
const d = new Date(v);
|
|
28
|
+
return Number.isNaN(d.getTime())
|
|
29
|
+
? new Date().toISOString().slice(0, 10)
|
|
30
|
+
: d.toISOString().slice(0, 10);
|
|
31
|
+
};
|
|
32
|
+
const uniq = (arr) => [
|
|
33
|
+
...new Set(arr.filter((s) => typeof s === "string" && s.trim())),
|
|
34
|
+
];
|
|
35
|
+
const slugify = (v) =>
|
|
36
|
+
String(v || "")
|
|
37
|
+
.trim()
|
|
38
|
+
.toLowerCase()
|
|
39
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
40
|
+
.replace(/^-+|-+$/g, "")
|
|
41
|
+
.slice(0, 80);
|
|
42
|
+
const buildId = (r) => {
|
|
43
|
+
const e = slugify(r.id);
|
|
44
|
+
if (e) return e;
|
|
45
|
+
const p = slugify(r.pattern);
|
|
46
|
+
return p || `adaptive-${Date.now()}`;
|
|
47
|
+
};
|
|
48
|
+
const readJson = (f, fb) => {
|
|
49
|
+
if (!existsSync(f)) return clone(fb);
|
|
50
|
+
try {
|
|
51
|
+
return { ...clone(fb), ...JSON.parse(readFileSync(f, "utf8")) };
|
|
52
|
+
} catch {
|
|
53
|
+
return clone(fb);
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
const writeJson = (f, v) =>
|
|
57
|
+
writeFileSync(f, `${JSON.stringify(v, null, 2)}\n`, "utf8");
|
|
58
|
+
const strip = (r) => {
|
|
59
|
+
if (!r) return null;
|
|
60
|
+
const { sessionIds, ...pub } = r;
|
|
61
|
+
return clone(pub);
|
|
62
|
+
};
|
|
63
|
+
const sortRules = (list) =>
|
|
64
|
+
[...list].sort(
|
|
65
|
+
(a, b) =>
|
|
66
|
+
a.tier - b.tier ||
|
|
67
|
+
b.confidence - a.confidence ||
|
|
68
|
+
a.id.localeCompare(b.id),
|
|
69
|
+
);
|
|
23
70
|
const upsert = (list, r) => [...list.filter((x) => x.id !== r.id), r];
|
|
24
71
|
const without = (list, id) => list.filter((x) => x.id !== id);
|
|
25
72
|
|
|
26
73
|
function toRule(rule, tier, sessionId, existing = null) {
|
|
27
74
|
return {
|
|
28
75
|
id: existing?.id || buildId(rule),
|
|
29
|
-
pattern: String(rule.pattern || existing?.pattern ||
|
|
30
|
-
rootCause: String(
|
|
31
|
-
|
|
76
|
+
pattern: String(rule.pattern || existing?.pattern || ""),
|
|
77
|
+
rootCause: String(
|
|
78
|
+
rule.rootCause || rule.root_cause || existing?.rootCause || "",
|
|
79
|
+
),
|
|
80
|
+
rule: String(rule.rule || existing?.rule || ""),
|
|
32
81
|
confidence: clamp01(rule.confidence ?? existing?.confidence),
|
|
33
82
|
occurrences: Math.max(1, Number(existing?.occurrences || 0) + 1),
|
|
34
83
|
firstSeen: existing?.firstSeen || toDate(rule.timestamp),
|
|
@@ -42,10 +91,10 @@ function toRule(rule, tier, sessionId, existing = null) {
|
|
|
42
91
|
|
|
43
92
|
export function createAdaptiveMemory(opts = {}) {
|
|
44
93
|
const projectSlug = slugify(opts.projectSlug);
|
|
45
|
-
if (!projectSlug) throw new Error(
|
|
94
|
+
if (!projectSlug) throw new Error("projectSlug is required");
|
|
46
95
|
|
|
47
|
-
const sessionDir = opts.sessionDir || join(process.cwd(),
|
|
48
|
-
const globalDir = opts.globalDir || join(homedir(),
|
|
96
|
+
const sessionDir = opts.sessionDir || join(process.cwd(), ".omc", "state");
|
|
97
|
+
const globalDir = opts.globalDir || join(homedir(), ".triflux", "adaptive");
|
|
49
98
|
const sessionFile = join(sessionDir, SESSION_FILE);
|
|
50
99
|
const projectFile = join(globalDir, `${projectSlug}.json`);
|
|
51
100
|
|
|
@@ -53,34 +102,58 @@ export function createAdaptiveMemory(opts = {}) {
|
|
|
53
102
|
mkdirSync(globalDir, { recursive: true });
|
|
54
103
|
|
|
55
104
|
let ss = readJson(sessionFile, { projectSlug, sessionId: null, rules: [] });
|
|
56
|
-
let ps = readJson(projectFile, {
|
|
105
|
+
let ps = readJson(projectFile, {
|
|
106
|
+
projectSlug,
|
|
107
|
+
history: {},
|
|
108
|
+
tier2: [],
|
|
109
|
+
tier3: [],
|
|
110
|
+
});
|
|
57
111
|
|
|
58
112
|
function saveSession() {
|
|
59
|
-
if (ss.rules.length === 0) {
|
|
113
|
+
if (ss.rules.length === 0) {
|
|
114
|
+
rmSync(sessionFile, { force: true });
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
60
117
|
writeJson(sessionFile, ss);
|
|
61
118
|
}
|
|
62
119
|
|
|
63
120
|
function saveProject() {
|
|
64
|
-
const has =
|
|
65
|
-
|
|
121
|
+
const has =
|
|
122
|
+
Object.keys(ps.history).length > 0 ||
|
|
123
|
+
ps.tier2.length > 0 ||
|
|
124
|
+
ps.tier3.length > 0;
|
|
125
|
+
if (!has) {
|
|
126
|
+
rmSync(projectFile, { force: true });
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
66
129
|
writeJson(projectFile, ps);
|
|
67
130
|
}
|
|
68
131
|
|
|
69
|
-
const saveAll = () => {
|
|
132
|
+
const saveAll = () => {
|
|
133
|
+
saveSession();
|
|
134
|
+
saveProject();
|
|
135
|
+
};
|
|
70
136
|
|
|
71
137
|
function getSessionId(id) {
|
|
72
|
-
const next = String(id || ss.sessionId ||
|
|
138
|
+
const next = String(id || ss.sessionId || "session-current");
|
|
73
139
|
ss = { ...ss, sessionId: next };
|
|
74
140
|
return next;
|
|
75
141
|
}
|
|
76
142
|
|
|
77
|
-
const getDurable = (id) =>
|
|
143
|
+
const getDurable = (id) =>
|
|
144
|
+
ps.tier3.find((r) => r.id === id) ||
|
|
145
|
+
ps.tier2.find((r) => r.id === id) ||
|
|
146
|
+
null;
|
|
78
147
|
|
|
79
148
|
function promote(ruleId) {
|
|
80
149
|
const t2 = ps.tier2.find((r) => r.id === ruleId);
|
|
81
150
|
if (t2 && t2.occurrences >= 3 && t2.confidence >= 0.8) {
|
|
82
151
|
const next = { ...t2, tier: 3, sessionsWithout: 0 };
|
|
83
|
-
ps = {
|
|
152
|
+
ps = {
|
|
153
|
+
...ps,
|
|
154
|
+
tier2: without(ps.tier2, ruleId),
|
|
155
|
+
tier3: upsert(ps.tier3, next),
|
|
156
|
+
};
|
|
84
157
|
saveProject();
|
|
85
158
|
return { rule: strip(next), promoted: true, fromTier: 2, toTier: 3 };
|
|
86
159
|
}
|
|
@@ -94,44 +167,80 @@ export function createAdaptiveMemory(opts = {}) {
|
|
|
94
167
|
return { rule: strip(next), promoted: true, fromTier: 1, toTier: 2 };
|
|
95
168
|
}
|
|
96
169
|
const cur = getDurable(ruleId) || ps.history[ruleId] || null;
|
|
97
|
-
return {
|
|
170
|
+
return {
|
|
171
|
+
rule: strip(cur),
|
|
172
|
+
promoted: false,
|
|
173
|
+
fromTier: cur?.tier ?? null,
|
|
174
|
+
toTier: cur?.tier ?? null,
|
|
175
|
+
};
|
|
98
176
|
}
|
|
99
177
|
|
|
100
178
|
function record(rule = {}) {
|
|
101
|
-
if (!rule.pattern)
|
|
179
|
+
if (!rule.pattern)
|
|
180
|
+
return { rule: null, promoted: false, fromTier: null, toTier: null };
|
|
102
181
|
const sessionId = getSessionId(rule.sessionId);
|
|
103
182
|
const ruleId = buildId(rule);
|
|
104
183
|
const durable = getDurable(ruleId);
|
|
105
184
|
if (durable) {
|
|
106
185
|
const next = toRule(rule, durable.tier, sessionId, durable);
|
|
107
|
-
ps =
|
|
186
|
+
ps =
|
|
187
|
+
durable.tier === 3
|
|
188
|
+
? { ...ps, tier3: upsert(ps.tier3, next) }
|
|
189
|
+
: { ...ps, tier2: upsert(ps.tier2, next) };
|
|
108
190
|
saveProject();
|
|
109
191
|
const res = promote(ruleId);
|
|
110
|
-
return res.promoted
|
|
192
|
+
return res.promoted
|
|
193
|
+
? res
|
|
194
|
+
: {
|
|
195
|
+
rule: strip(next),
|
|
196
|
+
promoted: false,
|
|
197
|
+
fromTier: durable.tier,
|
|
198
|
+
toTier: durable.tier,
|
|
199
|
+
};
|
|
111
200
|
}
|
|
112
201
|
const cand = toRule(rule, 1, sessionId, ps.history[ruleId]);
|
|
113
202
|
ps = { ...ps, history: { ...ps.history, [ruleId]: cand } };
|
|
114
203
|
ss = { ...ss, rules: upsert(ss.rules, { ...cand, tier: 1 }) };
|
|
115
204
|
saveAll();
|
|
116
205
|
const res = promote(ruleId);
|
|
117
|
-
return res.promoted
|
|
206
|
+
return res.promoted
|
|
207
|
+
? res
|
|
208
|
+
: { rule: strip(cand), promoted: false, fromTier: 1, toTier: 1 };
|
|
118
209
|
}
|
|
119
210
|
|
|
120
211
|
function decay(sessionId) {
|
|
121
212
|
const nextId = String(sessionId || `session-${Date.now()}`);
|
|
122
|
-
if (ss.sessionId === nextId)
|
|
123
|
-
|
|
213
|
+
if (ss.sessionId === nextId)
|
|
214
|
+
return {
|
|
215
|
+
sessionId: nextId,
|
|
216
|
+
tier1Cleared: 0,
|
|
217
|
+
updated: [],
|
|
218
|
+
warned: [],
|
|
219
|
+
removed: [],
|
|
220
|
+
};
|
|
221
|
+
const warned = [],
|
|
222
|
+
removed = [],
|
|
223
|
+
updated = [];
|
|
124
224
|
const tier1Cleared = ss.rules.length;
|
|
125
225
|
const tier2 = ps.tier2.flatMap((r) => {
|
|
126
226
|
const sw = Number(r.sessionsWithout || 0) + 1;
|
|
127
|
-
const conf =
|
|
128
|
-
|
|
227
|
+
const conf =
|
|
228
|
+
sw % TIER2_DECAY_INTERVAL === 0
|
|
229
|
+
? clamp01(r.confidence - TIER2_DECAY_STEP)
|
|
230
|
+
: r.confidence;
|
|
231
|
+
if (conf < TIER2_REMOVE_THRESHOLD) {
|
|
232
|
+
removed.push(r.id);
|
|
233
|
+
return [];
|
|
234
|
+
}
|
|
129
235
|
updated.push(r.id);
|
|
130
236
|
return [{ ...r, sessionsWithout: sw, confidence: conf }];
|
|
131
237
|
});
|
|
132
238
|
const tier3 = ps.tier3.flatMap((r) => {
|
|
133
239
|
const sw = Number(r.sessionsWithout || 0) + 1;
|
|
134
|
-
if (sw >= TIER3_REMOVE_THRESHOLD) {
|
|
240
|
+
if (sw >= TIER3_REMOVE_THRESHOLD) {
|
|
241
|
+
removed.push(r.id);
|
|
242
|
+
return [];
|
|
243
|
+
}
|
|
135
244
|
if (sw === TIER3_WARN_THRESHOLD) warned.push(r.id);
|
|
136
245
|
updated.push(r.id);
|
|
137
246
|
return [{ ...r, sessionsWithout: sw }];
|
|
@@ -142,17 +251,22 @@ export function createAdaptiveMemory(opts = {}) {
|
|
|
142
251
|
return { sessionId: nextId, tier1Cleared, updated, warned, removed };
|
|
143
252
|
}
|
|
144
253
|
|
|
145
|
-
function getRule(id) {
|
|
254
|
+
function getRule(id) {
|
|
255
|
+
return strip(ss.rules.find((r) => r.id === id) || getDurable(id));
|
|
256
|
+
}
|
|
146
257
|
function getTier(tier) {
|
|
147
258
|
if (tier === 1) return sortRules(ss.rules).map(strip);
|
|
148
259
|
if (tier === 2) return sortRules(ps.tier2).map(strip);
|
|
149
260
|
if (tier === 3) return sortRules(ps.tier3).map(strip);
|
|
150
261
|
return [];
|
|
151
262
|
}
|
|
152
|
-
function getAllRules() {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
263
|
+
function getAllRules() {
|
|
264
|
+
return sortRules([...ss.rules, ...ps.tier2, ...ps.tier3]).map(strip);
|
|
265
|
+
}
|
|
266
|
+
function reset(target = "all") {
|
|
267
|
+
const rs = target === "all" || target === 1 || target === "session";
|
|
268
|
+
const rp =
|
|
269
|
+
target === "all" || target === 2 || target === 3 || target === "project";
|
|
156
270
|
if (rs) ss = { ...ss, rules: [] };
|
|
157
271
|
if (rp) ps = { ...ps, history: {}, tier2: [], tier3: [] };
|
|
158
272
|
saveAll();
|
package/hub/adaptive.mjs
CHANGED
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { randomUUID } from
|
|
2
|
-
import { join } from
|
|
3
|
-
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import { createAdaptiveFingerprintService } from './session-fingerprint.mjs';
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { createDiagnosticPipeline } from "./adaptive-diagnostic.mjs";
|
|
4
|
+
import { createAdaptiveInjector } from "./adaptive-inject.mjs";
|
|
5
|
+
import { createAdaptiveMemory } from "./adaptive-memory.mjs";
|
|
6
|
+
import { createAdaptiveFingerprintService } from "./session-fingerprint.mjs";
|
|
8
7
|
|
|
9
8
|
let singletonEngine = null;
|
|
10
9
|
|
|
@@ -17,36 +16,55 @@ function toRuleList(value) {
|
|
|
17
16
|
}
|
|
18
17
|
|
|
19
18
|
function resolveTierCount(memory, tier) {
|
|
20
|
-
if (typeof memory.getTier ===
|
|
19
|
+
if (typeof memory.getTier === "function") {
|
|
21
20
|
const rules = memory.getTier(tier);
|
|
22
21
|
return Array.isArray(rules) ? rules.length : 0;
|
|
23
22
|
}
|
|
24
|
-
return toRuleList(memory.getAllRules?.()).filter(
|
|
23
|
+
return toRuleList(memory.getAllRules?.()).filter(
|
|
24
|
+
(rule) => Number(rule?.tier) === tier,
|
|
25
|
+
).length;
|
|
25
26
|
}
|
|
26
27
|
|
|
27
28
|
function resolveActiveRuleIds(memory, decayResult) {
|
|
28
|
-
if (Array.isArray(decayResult?.activeRuleIds))
|
|
29
|
-
|
|
29
|
+
if (Array.isArray(decayResult?.activeRuleIds))
|
|
30
|
+
return [...decayResult.activeRuleIds];
|
|
31
|
+
return toRuleList(memory.getAllRules?.())
|
|
32
|
+
.map((rule) => rule.id)
|
|
33
|
+
.filter(Boolean);
|
|
30
34
|
}
|
|
31
35
|
|
|
32
36
|
function resolveRecordedRule(recordResult) {
|
|
33
|
-
if (recordResult?.rule)
|
|
37
|
+
if (recordResult?.rule)
|
|
38
|
+
return {
|
|
39
|
+
rule: recordResult.rule,
|
|
40
|
+
promoted: Boolean(recordResult.promoted),
|
|
41
|
+
};
|
|
34
42
|
return { rule: recordResult || null, promoted: false };
|
|
35
43
|
}
|
|
36
44
|
|
|
37
45
|
function createEngineInstance(opts = {}) {
|
|
38
46
|
const repoRoot = opts.repoRoot || process.cwd();
|
|
39
|
-
const claudeMdPath = opts.claudeMdPath || join(repoRoot,
|
|
40
|
-
const projectSlug = String(opts.projectSlug ||
|
|
47
|
+
const claudeMdPath = opts.claudeMdPath || join(repoRoot, "CLAUDE.md");
|
|
48
|
+
const projectSlug = String(opts.projectSlug || "default").trim() || "default";
|
|
41
49
|
const now = opts.now || (() => Date.now());
|
|
42
50
|
const sessionIdFactory = opts.sessionIdFactory || (() => randomUUID());
|
|
43
51
|
|
|
44
|
-
const memory =
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
52
|
+
const memory =
|
|
53
|
+
opts.memory ||
|
|
54
|
+
opts.memoryFactory?.(opts) ||
|
|
55
|
+
createAdaptiveMemory({ projectSlug, ...opts.memoryOptions });
|
|
56
|
+
const diagnostic =
|
|
57
|
+
opts.diagnostic ||
|
|
58
|
+
opts.diagnosticFactory?.(opts) ||
|
|
59
|
+
createDiagnosticPipeline(opts.diagnosticOptions);
|
|
60
|
+
const injector =
|
|
61
|
+
opts.injector ||
|
|
62
|
+
opts.injectorFactory?.(opts) ||
|
|
63
|
+
createAdaptiveInjector({ claudeMdPath, ...opts.injectorOptions });
|
|
64
|
+
const fingerprintService =
|
|
65
|
+
opts.fingerprintService ||
|
|
66
|
+
opts.fingerprintFactory?.(opts) ||
|
|
67
|
+
createAdaptiveFingerprintService(opts.fingerprintOptions);
|
|
50
68
|
|
|
51
69
|
let started = false;
|
|
52
70
|
let currentSessionId = null;
|
|
@@ -57,12 +75,12 @@ function createEngineInstance(opts = {}) {
|
|
|
57
75
|
};
|
|
58
76
|
|
|
59
77
|
function refreshFingerprint() {
|
|
60
|
-
if (typeof fingerprintService.computeFingerprint !==
|
|
78
|
+
if (typeof fingerprintService.computeFingerprint !== "function") return;
|
|
61
79
|
const fingerprint = fingerprintService.computeFingerprint({
|
|
62
80
|
scope: projectSlug,
|
|
63
81
|
cwd: repoRoot,
|
|
64
82
|
filePath: claudeMdPath,
|
|
65
|
-
workType:
|
|
83
|
+
workType: "adaptive",
|
|
66
84
|
timestamp: now(),
|
|
67
85
|
});
|
|
68
86
|
lastFingerprintId = fingerprint?.fingerprint_id || lastFingerprintId;
|
|
@@ -71,7 +89,10 @@ function createEngineInstance(opts = {}) {
|
|
|
71
89
|
function startSession() {
|
|
72
90
|
if (started) return;
|
|
73
91
|
currentSessionId = sessionIdFactory();
|
|
74
|
-
const decayResult =
|
|
92
|
+
const decayResult =
|
|
93
|
+
typeof memory.decay === "function"
|
|
94
|
+
? memory.decay(currentSessionId)
|
|
95
|
+
: null;
|
|
75
96
|
injector.cleanup?.(resolveActiveRuleIds(memory, decayResult));
|
|
76
97
|
refreshFingerprint();
|
|
77
98
|
started = true;
|
|
@@ -91,13 +112,15 @@ function createEngineInstance(opts = {}) {
|
|
|
91
112
|
}
|
|
92
113
|
|
|
93
114
|
counters.diagnosedErrors += 1;
|
|
94
|
-
const { rule: recordedRule, promoted } = resolveRecordedRule(
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
115
|
+
const { rule: recordedRule, promoted } = resolveRecordedRule(
|
|
116
|
+
memory.record({
|
|
117
|
+
...diagnosis.rule,
|
|
118
|
+
confidence: diagnosis.confidence,
|
|
119
|
+
dnaFactor: diagnosis.dnaFactor,
|
|
120
|
+
sessionId: currentSessionId,
|
|
121
|
+
lastSeen: new Date(now()).toISOString().slice(0, 10),
|
|
122
|
+
}),
|
|
123
|
+
);
|
|
101
124
|
|
|
102
125
|
const nextRule = clone(recordedRule || diagnosis.rule);
|
|
103
126
|
if (nextRule?.tier >= 3 && promoted) {
|
|
@@ -127,7 +150,13 @@ function createEngineInstance(opts = {}) {
|
|
|
127
150
|
});
|
|
128
151
|
}
|
|
129
152
|
|
|
130
|
-
return Object.freeze({
|
|
153
|
+
return Object.freeze({
|
|
154
|
+
handleError,
|
|
155
|
+
startSession,
|
|
156
|
+
endSession,
|
|
157
|
+
getStats,
|
|
158
|
+
__lastFingerprintId: () => lastFingerprintId,
|
|
159
|
+
});
|
|
131
160
|
}
|
|
132
161
|
|
|
133
162
|
export function createAdaptiveEngine(opts = {}) {
|
package/hub/assign-callbacks.mjs
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
// hub/assign-callbacks.mjs — assign job 상태 변경용 Named Pipe/Unix socket 브로드캐스터
|
|
2
2
|
|
|
3
|
-
import
|
|
4
|
-
import
|
|
5
|
-
import { IS_WINDOWS, pipePath } from
|
|
3
|
+
import { existsSync, unlinkSync } from "node:fs";
|
|
4
|
+
import net from "node:net";
|
|
5
|
+
import { IS_WINDOWS, pipePath } from "./platform.mjs";
|
|
6
6
|
|
|
7
7
|
export function getAssignCallbackPipePath(sessionId = process.pid) {
|
|
8
|
-
return pipePath(
|
|
8
|
+
return pipePath("triflux-assign-callback", sessionId);
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
function buildAssignCallbackEvent(event = {}, row = null) {
|
|
@@ -14,42 +14,71 @@ function buildAssignCallbackEvent(event = {}, row = null) {
|
|
|
14
14
|
const createdAtMs = Number(source.created_at_ms);
|
|
15
15
|
const timestampMs = Number.isFinite(updatedAtMs)
|
|
16
16
|
? updatedAtMs
|
|
17
|
-
:
|
|
17
|
+
: Number.isFinite(createdAtMs)
|
|
18
|
+
? createdAtMs
|
|
19
|
+
: Date.now();
|
|
18
20
|
|
|
19
21
|
return {
|
|
20
|
-
event:
|
|
22
|
+
event: "assign_job_status",
|
|
21
23
|
job_id: source.job_id || event.job_id || null,
|
|
22
24
|
supervisor_agent: source.supervisor_agent || null,
|
|
23
25
|
worker_agent: source.worker_agent || null,
|
|
24
26
|
topic: source.topic || null,
|
|
25
27
|
task: source.task || null,
|
|
26
28
|
status: source.status || event.status || null,
|
|
27
|
-
attempt: Number.isFinite(Number(source.attempt))
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
29
|
+
attempt: Number.isFinite(Number(source.attempt))
|
|
30
|
+
? Number(source.attempt)
|
|
31
|
+
: null,
|
|
32
|
+
retry_count: Number.isFinite(Number(source.retry_count))
|
|
33
|
+
? Number(source.retry_count)
|
|
34
|
+
: null,
|
|
35
|
+
max_retries: Number.isFinite(Number(source.max_retries))
|
|
36
|
+
? Number(source.max_retries)
|
|
37
|
+
: null,
|
|
38
|
+
priority: Number.isFinite(Number(source.priority))
|
|
39
|
+
? Number(source.priority)
|
|
40
|
+
: null,
|
|
41
|
+
ttl_ms: Number.isFinite(Number(source.ttl_ms))
|
|
42
|
+
? Number(source.ttl_ms)
|
|
43
|
+
: null,
|
|
44
|
+
timeout_ms: Number.isFinite(Number(source.timeout_ms))
|
|
45
|
+
? Number(source.timeout_ms)
|
|
46
|
+
: null,
|
|
47
|
+
deadline_ms: Number.isFinite(Number(source.deadline_ms))
|
|
48
|
+
? Number(source.deadline_ms)
|
|
49
|
+
: null,
|
|
34
50
|
trace_id: source.trace_id || null,
|
|
35
51
|
correlation_id: source.correlation_id || null,
|
|
36
52
|
last_message_id: source.last_message_id || null,
|
|
37
|
-
result: Object.hasOwn(source,
|
|
53
|
+
result: Object.hasOwn(source, "result")
|
|
38
54
|
? source.result
|
|
39
|
-
:
|
|
40
|
-
|
|
55
|
+
: Object.hasOwn(event, "result")
|
|
56
|
+
? event.result
|
|
57
|
+
: null,
|
|
58
|
+
error: Object.hasOwn(source, "error")
|
|
41
59
|
? source.error
|
|
42
|
-
:
|
|
60
|
+
: Object.hasOwn(event, "error")
|
|
61
|
+
? event.error
|
|
62
|
+
: null,
|
|
43
63
|
created_at_ms: Number.isFinite(createdAtMs) ? createdAtMs : null,
|
|
44
64
|
updated_at_ms: Number.isFinite(updatedAtMs) ? updatedAtMs : null,
|
|
45
|
-
started_at_ms: Number.isFinite(Number(source.started_at_ms))
|
|
46
|
-
|
|
47
|
-
|
|
65
|
+
started_at_ms: Number.isFinite(Number(source.started_at_ms))
|
|
66
|
+
? Number(source.started_at_ms)
|
|
67
|
+
: null,
|
|
68
|
+
completed_at_ms: Number.isFinite(Number(source.completed_at_ms))
|
|
69
|
+
? Number(source.completed_at_ms)
|
|
70
|
+
: null,
|
|
71
|
+
last_retry_at_ms: Number.isFinite(Number(source.last_retry_at_ms))
|
|
72
|
+
? Number(source.last_retry_at_ms)
|
|
73
|
+
: null,
|
|
48
74
|
timestamp: new Date(timestampMs).toISOString(),
|
|
49
75
|
};
|
|
50
76
|
}
|
|
51
77
|
|
|
52
|
-
export function createAssignCallbackServer({
|
|
78
|
+
export function createAssignCallbackServer({
|
|
79
|
+
store = null,
|
|
80
|
+
sessionId = process.pid,
|
|
81
|
+
} = {}) {
|
|
53
82
|
const pipePath = getAssignCallbackPipePath(sessionId);
|
|
54
83
|
const clients = new Set();
|
|
55
84
|
let server = null;
|
|
@@ -58,7 +87,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
|
|
|
58
87
|
function removeSocket(socket) {
|
|
59
88
|
if (!socket) return;
|
|
60
89
|
clients.delete(socket);
|
|
61
|
-
try {
|
|
90
|
+
try {
|
|
91
|
+
socket.destroy();
|
|
92
|
+
} catch {}
|
|
62
93
|
}
|
|
63
94
|
|
|
64
95
|
function broadcast(event) {
|
|
@@ -87,20 +118,22 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
|
|
|
87
118
|
async start() {
|
|
88
119
|
if (server) return { path: pipePath };
|
|
89
120
|
if (!IS_WINDOWS && existsSync(pipePath)) {
|
|
90
|
-
try {
|
|
121
|
+
try {
|
|
122
|
+
unlinkSync(pipePath);
|
|
123
|
+
} catch {}
|
|
91
124
|
}
|
|
92
125
|
|
|
93
126
|
server = net.createServer((socket) => {
|
|
94
127
|
clients.add(socket);
|
|
95
|
-
socket.setEncoding(
|
|
96
|
-
socket.on(
|
|
97
|
-
socket.on(
|
|
128
|
+
socket.setEncoding("utf8");
|
|
129
|
+
socket.on("error", () => removeSocket(socket));
|
|
130
|
+
socket.on("close", () => removeSocket(socket));
|
|
98
131
|
});
|
|
99
132
|
|
|
100
133
|
await new Promise((resolve, reject) => {
|
|
101
|
-
server.once(
|
|
134
|
+
server.once("error", reject);
|
|
102
135
|
server.listen(pipePath, () => {
|
|
103
|
-
server?.off(
|
|
136
|
+
server?.off("error", reject);
|
|
104
137
|
resolve();
|
|
105
138
|
});
|
|
106
139
|
});
|
|
@@ -115,7 +148,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
|
|
|
115
148
|
},
|
|
116
149
|
async stop() {
|
|
117
150
|
if (detachStoreListener) {
|
|
118
|
-
try {
|
|
151
|
+
try {
|
|
152
|
+
detachStoreListener();
|
|
153
|
+
} catch {}
|
|
119
154
|
detachStoreListener = null;
|
|
120
155
|
}
|
|
121
156
|
if (!server) return;
|
|
@@ -125,7 +160,9 @@ export function createAssignCallbackServer({ store = null, sessionId = process.p
|
|
|
125
160
|
await new Promise((resolve) => server.close(resolve));
|
|
126
161
|
server = null;
|
|
127
162
|
if (!IS_WINDOWS && existsSync(pipePath)) {
|
|
128
|
-
try {
|
|
163
|
+
try {
|
|
164
|
+
unlinkSync(pipePath);
|
|
165
|
+
} catch {}
|
|
129
166
|
}
|
|
130
167
|
},
|
|
131
168
|
broadcast,
|
package/hub/bridge.mjs
CHANGED
|
@@ -342,7 +342,6 @@ async function pipeQuery(action, payload, timeoutMs = 3000) {
|
|
|
342
342
|
export function parseArgs(argv) {
|
|
343
343
|
const { values, positionals } = nodeParseArgs({
|
|
344
344
|
args: argv,
|
|
345
|
-
allowPositionals: true,
|
|
346
345
|
options: {
|
|
347
346
|
agent: { type: "string" },
|
|
348
347
|
cli: { type: "string" },
|