@triflux/core 10.50.2 → 10.52.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 (84) hide show
  1. package/hooks/agy-session-hook.mjs +11 -56
  2. package/hooks/codex-session-hook.mjs +11 -101
  3. package/hub/bridge.mjs +65 -1250
  4. package/hub/cli-adapter-base.mjs +12 -90
  5. package/hub/codex-adapter.mjs +0 -1
  6. package/hub/codex-preflight.mjs +5 -28
  7. package/hub/index.mjs +3 -19
  8. package/hub/lib/process-utils.mjs +1 -156
  9. package/hub/lib/spawn-trace.mjs +3 -2
  10. package/hub/lib/timeout-defaults.mjs +0 -1
  11. package/hub/team/claude-daemon-control.mjs +1 -2
  12. package/hub/team/claude-session-projection.mjs +5 -73
  13. package/hub/team/nativeProxy.mjs +759 -0
  14. package/hub/team/session-context.mjs +1 -1
  15. package/hud/cli-policy.mjs +0 -22
  16. package/hud/constants.mjs +13 -26
  17. package/hud/hud-qos-status.mjs +42 -54
  18. package/hud/providers/gemini.mjs +125 -20
  19. package/hud/renderers.mjs +101 -122
  20. package/hud/utils.mjs +10 -6
  21. package/package.json +2 -6
  22. package/scripts/lib/agent-route-policy.mjs +143 -62
  23. package/scripts/lib/cli-claude.mjs +0 -14
  24. package/scripts/lib/env-probe.mjs +2 -131
  25. package/scripts/lib/gemini-profiles.mjs +2 -69
  26. package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
  27. package/scripts/lib/machine-profile.mjs +3 -17
  28. package/scripts/lib/mcp-filter.mjs +109 -53
  29. package/scripts/lib/mcp-guard-engine.mjs +40 -98
  30. package/scripts/lib/mcp-health.mjs +2 -2
  31. package/scripts/lib/mcp-server-catalog.mjs +2 -2
  32. package/scripts/lib/psmux-info.mjs +11 -59
  33. package/scripts/lib/session-presence.mjs +2 -100
  34. package/scripts/lib/skill-template.mjs +0 -245
  35. package/hub/adaptive-diagnostic.mjs +0 -350
  36. package/hub/adaptive-inject.mjs +0 -224
  37. package/hub/adaptive-memory.mjs +0 -277
  38. package/hub/adaptive.mjs +0 -172
  39. package/hub/assign-callbacks.mjs +0 -170
  40. package/hub/delegator/contracts.mjs +0 -38
  41. package/hub/delegator/index.mjs +0 -14
  42. package/hub/delegator/schema/delegator-tools.schema.json +0 -250
  43. package/hub/delegator/service.mjs +0 -336
  44. package/hub/delegator/tool-definitions.mjs +0 -35
  45. package/hub/dynamic-routing-engine.mjs +0 -511
  46. package/hub/hitl.mjs +0 -202
  47. package/hub/lib/known-errors.json +0 -72
  48. package/hub/lib/memory-store.mjs +0 -1001
  49. package/hub/lib/phase-manager.mjs +0 -493
  50. package/hub/lib/risk-tier.mjs +0 -53
  51. package/hub/lib/ssh-command.mjs +0 -231
  52. package/hub/lib/staged-file-detect.mjs +0 -43
  53. package/hub/lib/state-snapshot.mjs +0 -293
  54. package/hub/lib/tfx-route-args.mjs +0 -353
  55. package/hub/lib/trace-recorder.mjs +0 -153
  56. package/hub/lib/uuidv7.mjs +0 -45
  57. package/hub/memory-doctor.mjs +0 -640
  58. package/hub/middleware/quota-middleware.mjs +0 -70
  59. package/hub/middleware/request-logger.mjs +0 -191
  60. package/hub/paths.mjs +0 -24
  61. package/hub/pipeline/index.mjs +0 -163
  62. package/hub/pipeline/state.mjs +0 -191
  63. package/hub/pipeline/transitions.mjs +0 -131
  64. package/hub/reflexion.mjs +0 -290
  65. package/hub/role-contract.mjs +0 -314
  66. package/hub/router.mjs +0 -2026
  67. package/hub/routing-snapshot.mjs +0 -261
  68. package/hub/session-fingerprint.mjs +0 -418
  69. package/hub/state.mjs +0 -300
  70. package/hub/team/synapse-http.mjs +0 -311
  71. package/hub/team-bridge.mjs +0 -27
  72. package/mesh/index.mjs +0 -69
  73. package/mesh/mesh-budget.mjs +0 -137
  74. package/mesh/mesh-heartbeat.mjs +0 -100
  75. package/mesh/mesh-protocol.mjs +0 -96
  76. package/mesh/mesh-queue.mjs +0 -163
  77. package/mesh/mesh-registry.mjs +0 -78
  78. package/mesh/mesh-router.mjs +0 -77
  79. package/scripts/lib/claudemd-scanner.mjs +0 -223
  80. package/scripts/lib/context.mjs +0 -67
  81. package/scripts/lib/dynamic-route-cli.mjs +0 -107
  82. package/scripts/lib/handoff.mjs +0 -187
  83. package/scripts/lib/logger.mjs +0 -122
  84. package/scripts/lib/stealth-fetch.mjs +0 -176
@@ -2,23 +2,11 @@
2
2
 
3
3
  import { argv, exit, stdin, stdout } from "node:process";
4
4
  import { pathToFileURL } from "node:url";
5
- import { drainPendingSynapse as defaultDrainPendingSynapse } from "../hub/team/synapse-http.mjs";
6
5
  import {
7
- heartbeatInteractiveSession as defaultHeartbeatInteractiveSession,
8
- registerInteractiveSession as defaultRegisterInteractiveSession,
6
+ emitParticipantSessionStarted,
7
+ shouldSkipInteractiveRegistration,
9
8
  } from "../scripts/lib/session-presence.mjs";
10
9
 
11
- // hub-ensure is loaded lazily so the byte-identical packages/core mirror of this
12
- // file loads cleanly. packages/core mirrors scripts/lib only (not scripts/*), so a
13
- // static `../scripts/hub-ensure.mjs` import would make the core copy throw
14
- // ERR_MODULE_NOT_FOUND at load time. Mirrors codex-session-hook.mjs's pattern.
15
- async function defaultHubEnsureRun(stdinData) {
16
- const { run } = await import(
17
- new URL("../scripts/hub-ensure.mjs", import.meta.url).href
18
- );
19
- return run(stdinData);
20
- }
21
-
22
10
  function parsePayload(stdinData) {
23
11
  try {
24
12
  const raw = typeof stdinData === "string" ? stdinData : "";
@@ -76,8 +64,7 @@ export function normalizeMode(argvMode, payload) {
76
64
  if (Number.isFinite(invocationNum)) {
77
65
  return invocationNum <= 1 ? "register" : "heartbeat";
78
66
  }
79
- // Unknown invocation index: register is idempotent and also ensures the hub,
80
- // so it is the safe default for a first-contact payload.
67
+ // 첫 호출 정보가 없으면 시작 기록을 남긴다.
81
68
  return "register";
82
69
  }
83
70
 
@@ -108,23 +95,6 @@ async function runHookSideEffectsWithStdoutSuppressed(fn) {
108
95
  }
109
96
  }
110
97
 
111
- /**
112
- * Execute the observational Antigravity session hook.
113
- *
114
- * The hook always returns/writes an empty JSON object so hook stdout remains
115
- * JSON-only and hook failures never block the user session.
116
- *
117
- * @param {string} stdinData
118
- * @param {{
119
- * argvMode?: string,
120
- * writeStdout?: boolean,
121
- * hubEnsureRun?: (stdinData: string) => Promise<unknown> | unknown,
122
- * registerInteractiveSession?: (stdinData: string) => Promise<unknown> | unknown,
123
- * heartbeatInteractiveSession?: (stdinData: string) => Promise<unknown> | unknown,
124
- * drainPendingSynapse?: (timeoutMs?: number) => Promise<unknown> | unknown,
125
- * }} [opts]
126
- * @returns {Promise<string>}
127
- */
128
98
  export async function runAgySessionHook(stdinData, opts = {}) {
129
99
  const output = "{}\n";
130
100
  const parsed = parsePayload(stdinData);
@@ -142,37 +112,22 @@ export async function runAgySessionHook(stdinData, opts = {}) {
142
112
  }
143
113
 
144
114
  const mode = normalizeMode(opts.argvMode ?? argv[2], parsed.payload);
145
- const hubEnsureRun = opts.hubEnsureRun || defaultHubEnsureRun;
146
- const registerInteractiveSession =
147
- opts.registerInteractiveSession || defaultRegisterInteractiveSession;
148
- const heartbeatInteractiveSession =
149
- opts.heartbeatInteractiveSession || defaultHeartbeatInteractiveSession;
150
- const drainPendingSynapse =
151
- opts.drainPendingSynapse || defaultDrainPendingSynapse;
115
+ const emitSessionStarted =
116
+ opts.emitSessionStarted || emitParticipantSessionStarted;
152
117
 
153
118
  try {
154
119
  await runHookSideEffectsWithStdoutSuppressed(async () => {
155
- if (mode === "register") {
156
- try {
157
- await hubEnsureRun(sessionPayload);
158
- } catch {}
159
- try {
160
- await Promise.resolve(registerInteractiveSession(sessionPayload));
161
- } catch {}
162
- try {
163
- await drainPendingSynapse(1000);
164
- } catch {}
165
- } else if (mode === "heartbeat") {
166
- try {
167
- heartbeatInteractiveSession(sessionPayload);
168
- } catch {}
120
+ if (
121
+ mode === "register" &&
122
+ !shouldSkipInteractiveRegistration(JSON.parse(sessionPayload), opts)
123
+ ) {
169
124
  try {
170
- await drainPendingSynapse(500);
125
+ await emitSessionStarted(sessionPayload);
171
126
  } catch {}
172
127
  }
173
128
  });
174
129
  } catch {
175
- // agy session hooks are observational and must never block the session.
130
+ // 로컬 기록 실패가 세션을 막지 않게 한다.
176
131
  }
177
132
 
178
133
  if (opts.writeStdout !== false) {
@@ -1,23 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { spawn } from "node:child_process";
4
3
  import { argv, exit, stdin, stdout } from "node:process";
5
- import { fileURLToPath, pathToFileURL } from "node:url";
4
+ import { pathToFileURL } from "node:url";
6
5
  import { writeCodexSessionRecord } from "../hub/lib/codex-session-registry.mjs";
7
- import { drainPendingSynapse as defaultDrainPendingSynapse } from "../hub/team/synapse-http.mjs";
8
6
  import {
9
- heartbeatInteractiveSession as defaultHeartbeatInteractiveSession,
10
- registerInteractiveSession as defaultRegisterInteractiveSession,
7
+ emitParticipantSessionStarted,
8
+ shouldSkipInteractiveRegistration,
11
9
  } from "../scripts/lib/session-presence.mjs";
12
10
 
13
- // hub-ensure가 없는 core 미러도 불러올 수 있도록 지연 import한다.
14
- async function defaultHubEnsureRun(stdinData) {
15
- const { run } = await import(
16
- new URL("../scripts/hub-ensure.mjs", import.meta.url).href
17
- );
18
- return run(stdinData);
19
- }
20
-
21
11
  function parsePayload(stdinData) {
22
12
  try {
23
13
  const raw = typeof stdinData === "string" ? stdinData : "";
@@ -48,66 +38,6 @@ function normalizeMode(mode, payload) {
48
38
  return "";
49
39
  }
50
40
 
51
- /**
52
- * Start a detached bridge call so Codex/OMX presence reaches both the Synapse
53
- * session registry and the hub agents table. This is intentionally independent
54
- * of the legacy session-start work below: a missing or unavailable hub must
55
- * never delay or fail SessionStart.
56
- */
57
- export function launchCodexPresenceRegistration(payload, opts = {}) {
58
- try {
59
- const sessionId = String(payload?.session_id || "").trim();
60
- if (!sessionId) return false;
61
-
62
- const cwd =
63
- typeof payload?.cwd === "string" && payload.cwd.trim()
64
- ? payload.cwd
65
- : process.cwd();
66
- const bridgePath =
67
- opts.bridgePath ||
68
- fileURLToPath(new URL("../hub/bridge.mjs", import.meta.url));
69
- const spawnFn = opts.spawnFn || spawn;
70
- const canonicalSessionId = String(process.env.OMX_SESSION_ID || "").trim();
71
- const tmuxSession = String(
72
- process.env.OMX_TMUX_SESSION_NAME || process.env.OMX_TMUX_SESSION || "",
73
- ).trim();
74
- const tmuxPane = String(process.env.TMUX_PANE || "").trim();
75
- const args = [
76
- bridgePath,
77
- "register",
78
- "--session-id",
79
- sessionId,
80
- "--cwd",
81
- cwd,
82
- "--worktree-path",
83
- cwd,
84
- "--session-kind",
85
- "interactive",
86
- "--host",
87
- "local",
88
- "--codex-session-id",
89
- sessionId,
90
- ];
91
- if (canonicalSessionId && canonicalSessionId !== sessionId) {
92
- args.push("--omx-session-id", canonicalSessionId);
93
- }
94
- if (tmuxSession) args.push("--tmux-session", tmuxSession);
95
- if (tmuxPane) args.push("--tmux-pane", tmuxPane);
96
-
97
- const child = spawnFn(process.execPath, args, {
98
- detached: true,
99
- stdio: "ignore",
100
- windowsHide: true,
101
- env: process.env,
102
- });
103
- child?.once?.("error", () => {});
104
- child?.unref?.();
105
- return true;
106
- } catch {
107
- return false;
108
- }
109
- }
110
-
111
41
  function swallowStdoutWrite(_chunk, encodingOrCallback, callback) {
112
42
  const done =
113
43
  typeof encodingOrCallback === "function" ? encodingOrCallback : callback;
@@ -142,15 +72,8 @@ export async function runCodexSessionHook(stdinData, opts = {}) {
142
72
  ? normalizeMode(opts.argvMode ?? argv[2], parsed.payload)
143
73
  : "";
144
74
  const writeSessionRecord = opts.writeSessionRecord || writeCodexSessionRecord;
145
- const hubEnsureRun = opts.hubEnsureRun || defaultHubEnsureRun;
146
- const registerInteractiveSession =
147
- opts.registerInteractiveSession || defaultRegisterInteractiveSession;
148
- const heartbeatInteractiveSession =
149
- opts.heartbeatInteractiveSession || defaultHeartbeatInteractiveSession;
150
- const drainPendingSynapse =
151
- opts.drainPendingSynapse || defaultDrainPendingSynapse;
152
- const launchPresenceRegistration =
153
- opts.launchPresenceRegistration || launchCodexPresenceRegistration;
75
+ const emitSessionStarted =
76
+ opts.emitSessionStarted || emitParticipantSessionStarted;
154
77
 
155
78
  try {
156
79
  await runHookSideEffectsWithStdoutSuppressed(async () => {
@@ -159,30 +82,17 @@ export async function runCodexSessionHook(stdinData, opts = {}) {
159
82
  writeSessionRecord(parsed.payload);
160
83
  } catch {}
161
84
  }
162
- if (mode === "register") {
163
- try {
164
- launchPresenceRegistration(parsed.payload);
165
- } catch {}
166
- try {
167
- await hubEnsureRun(stdinData);
168
- } catch {}
169
- try {
170
- await Promise.resolve(registerInteractiveSession(stdinData));
171
- } catch {}
172
- try {
173
- await drainPendingSynapse(1000);
174
- } catch {}
175
- } else if (mode === "heartbeat") {
176
- try {
177
- heartbeatInteractiveSession(stdinData);
178
- } catch {}
85
+ if (
86
+ mode === "register" &&
87
+ !shouldSkipInteractiveRegistration(parsed.payload, opts)
88
+ ) {
179
89
  try {
180
- await drainPendingSynapse(500);
90
+ await emitSessionStarted(stdinData);
181
91
  } catch {}
182
92
  }
183
93
  });
184
94
  } catch {
185
- // Codex session hooks are observational and must never block the session.
95
+ // 로컬 기록 실패가 세션을 막지 않게 한다.
186
96
  }
187
97
 
188
98
  if (opts.writeStdout !== false) {