@triflux/remote 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 (62) hide show
  1. package/cto/brief.mjs +0 -8
  2. package/cto/collect.mjs +1 -127
  3. package/cto/current.schema.json +2 -19
  4. package/cto/hygiene.mjs +2 -61
  5. package/cto/lake-root.mjs +0 -56
  6. package/cto/status.mjs +5 -139
  7. package/hub/index.mjs +0 -9
  8. package/hub/team/agents-row-attach.py +120 -0
  9. package/hub/team/agents-row.mjs +200 -0
  10. package/hub/team/claude-daemon-control.mjs +1 -2
  11. package/hub/team/claude-session-projection.mjs +5 -73
  12. package/hub/team/claude-transcript.mjs +19 -0
  13. package/hub/team/cli/commands/debug.mjs +1 -2
  14. package/hub/team/cli/commands/start/index.mjs +2 -1
  15. package/hub/team/cli/commands/start/start-headless.mjs +2 -0
  16. package/hub/team/cli/commands/start/start-mux.mjs +2 -4
  17. package/hub/team/cli/services/state-store.mjs +5 -20
  18. package/hub/team/headless.mjs +132 -551
  19. package/hub/team/psmux.mjs +3 -33
  20. package/hub/team/results-index.mjs +92 -0
  21. package/hub/team/session-context.mjs +1 -1
  22. package/hub/team/tui-viewer.mjs +9 -56
  23. package/hub/team/tui.mjs +0 -37
  24. package/hub/team/uds-orchestrator.mjs +20 -599
  25. package/hub/workers/factory.mjs +6 -51
  26. package/hub/workers/interface.mjs +1 -7
  27. package/hub/workers/lib/jsonrpc-core.mjs +11 -0
  28. package/hub/workers/lib/jsonrpc-ws-uds.mjs +5 -6
  29. package/package.json +3 -8
  30. package/scripts/lib/agent-route-policy.mjs +0 -67
  31. package/scripts/lib/cli-claude.mjs +0 -12
  32. package/scripts/lib/env-probe.mjs +0 -70
  33. package/scripts/lib/legacy-mcp-cleanup.mjs +283 -0
  34. package/scripts/lib/mcp-guard-engine.mjs +42 -101
  35. package/hub/hub-lifecycle.mjs +0 -248
  36. package/hub/pipe.mjs +0 -825
  37. package/hub/promote-penalties.mjs +0 -138
  38. package/hub/public/dashboard.html +0 -416
  39. package/hub/schema.sql +0 -209
  40. package/hub/server.mjs +0 -3048
  41. package/hub/store-adapter.mjs +0 -182
  42. package/hub/store.mjs +0 -1736
  43. package/hub/team/cli/services/hub-client.mjs +0 -178
  44. package/hub/team/conductor-registry.mjs +0 -121
  45. package/hub/team/cto-auto-collect.mjs +0 -115
  46. package/hub/team/lead-control.mjs +0 -191
  47. package/hub/team/session-sync.mjs +0 -316
  48. package/hub/team/swarm-intent.mjs +0 -18
  49. package/hub/team/synapse-cli.mjs +0 -458
  50. package/hub/team/synapse-http.mjs +0 -311
  51. package/hub/team/synapse-registry.mjs +0 -618
  52. package/hub/team/tui-synapse.mjs +0 -223
  53. package/hub/team/worker-sandbox.mjs +0 -125
  54. package/hub/tools.mjs +0 -900
  55. package/hub/workers/codex-app-server-worker.mjs +0 -1067
  56. package/hub/workers/delegator-mcp.mjs +0 -1098
  57. package/hub/workers/lib/jsonrpc-stdio.mjs +0 -204
  58. package/scripts/lib/claudemd-scanner.mjs +0 -26
  59. package/scripts/lib/context.mjs +0 -51
  60. package/scripts/lib/handoff.mjs +0 -187
  61. package/scripts/lib/logger.mjs +0 -122
  62. package/scripts/lib/stealth-fetch.mjs +0 -176
@@ -1,54 +1,13 @@
1
1
  // hub/workers/factory.mjs — Worker 생성 팩토리
2
2
  //
3
3
  // Supported worker types:
4
- // - 'claude' → ClaudeWorker
5
- // - 'codex' → CodexMcpWorker (default) or CodexAppServerWorker when
6
- // opts.transport === 'app-server'
7
- // - 'codex-app-server' → CodexAppServerWorker (explicit alias)
8
- // - 'delegator' → DelegatorMcpWorker
4
+ // - 'claude' → ClaudeWorker
5
+ // - 'codex' → CodexMcpWorker
9
6
  //
10
7
  import { ClaudeWorker } from "./claude-worker.mjs";
11
- import { CodexAppServerWorker } from "./codex-app-server-worker.mjs";
12
8
 
13
9
  /**
14
- * 호출자가 지정한 발행 콜백만 연결한다.
15
- *
16
- * Issue #95 P1 #4 validation: the app-server transport does not yet implement
17
- * the server-initiated approval / `tool/requestUserInput` round-trip. Any
18
- * `approvalPolicy !== 'never'` would cause a codex turn to hang waiting for
19
- * an approval response the worker cannot produce. Reject such configs at
20
- * factory time with a clear, actionable message.
21
- *
22
- * @param {object} [opts]
23
- */
24
- async function createCodexWorker(opts = {}) {
25
- const { transport, requestJsonFn, publishCallback, ...rest } = opts;
26
- void requestJsonFn;
27
-
28
- if (transport === "app-server") {
29
- const policy = rest.approvalPolicy;
30
- if (policy !== undefined && policy !== null && policy !== "never") {
31
- throw new Error(
32
- `codex app-server transport currently requires approvalPolicy='never' (got '${policy}'). ` +
33
- "The server-initiated approval / tool/requestUserInput round-trip is not yet implemented. " +
34
- "Set approvalPolicy='never' or use transport='mcp'. " +
35
- "Tracked in follow-up issue.",
36
- );
37
- }
38
- return new CodexAppServerWorker({
39
- ...rest,
40
- publishCallback:
41
- typeof publishCallback === "function" ? publishCallback : null,
42
- });
43
- }
44
-
45
- // Default (and transport === 'mcp'): CodexMcpWorker with zero new deps.
46
- const { CodexMcpWorker } = await import("./codex-mcp.mjs");
47
- return new CodexMcpWorker(rest);
48
- }
49
-
50
- /**
51
- * @param {'claude'|'codex'|'codex-app-server'|'delegator'} type
10
+ * @param {'claude'|'codex'} type
52
11
  * @param {object} [opts]
53
12
  * @returns {Promise<import('./interface.mjs').IWorker>}
54
13
  */
@@ -56,13 +15,9 @@ export async function createWorker(type, opts = {}) {
56
15
  switch (type) {
57
16
  case "claude":
58
17
  return new ClaudeWorker(opts);
59
- case "codex":
60
- return createCodexWorker(opts);
61
- case "codex-app-server":
62
- return createCodexWorker({ ...opts, transport: "app-server" });
63
- case "delegator": {
64
- const { DelegatorMcpWorker } = await import("./delegator-mcp.mjs");
65
- return new DelegatorMcpWorker(opts);
18
+ case "codex": {
19
+ const { CodexMcpWorker } = await import("./codex-mcp.mjs");
20
+ return new CodexMcpWorker(opts);
66
21
  }
67
22
  default:
68
23
  throw new Error(`Unknown worker type: ${type}`);
@@ -16,15 +16,11 @@
16
16
  * @property {string} [developerInstructions] - 개발자 지침
17
17
  * @property {string} [compactPrompt] - 컴팩션 프롬프트
18
18
  * @property {number} [timeoutMs] - MCP 요청 타임아웃(ms)
19
- * @property {'mcp'|'app-server'} [transport] - Codex 전송 계층 선택 (팩토리 전용)
20
19
  */
21
20
 
22
21
  /**
23
22
  * Codex 워커 생성 옵션 (팩토리 레벨)
24
23
  * @typedef {object} CodexWorkerFactoryOptions
25
- * @property {'mcp'|'app-server'} [transport] - 'mcp' (기본) 또는 'app-server'
26
- * @property {(publishMessage: object) => void|Promise<void>} [publishCallback] - app-server 전용 publish 후크
27
- * @property {(path: string, opts?: object) => Promise<unknown>} [requestJsonFn] - 테스트/리팩터용 requestJson 주입
28
24
  * @property {string} [command] - codex 실행 바이너리 경로
29
25
  * @property {string[]} [args] - codex CLI 인자 배열
30
26
  * @property {string} [cwd] - 워커 작업 디렉터리
@@ -61,14 +57,12 @@
61
57
  * @property {() => Promise<void>} start
62
58
  * @property {() => Promise<void>} stop
63
59
  * @property {() => boolean} isReady
64
- * @property {'codex'|'codex-app-server'|'gemini'|'antigravity'|'claude'|'delegator'} type
60
+ * @property {'codex'|'gemini'|'antigravity'|'claude'} type
65
61
  */
66
62
 
67
63
  export const WORKER_TYPES = Object.freeze([
68
64
  "codex",
69
- "codex-app-server",
70
65
  "gemini",
71
66
  "antigravity",
72
67
  "claude",
73
- "delegator",
74
68
  ]);
@@ -12,6 +12,17 @@ export class JsonRpcProtocolError extends Error {
12
12
  }
13
13
  }
14
14
 
15
+ /**
16
+ * Thrown when the underlying stream closes unexpectedly.
17
+ */
18
+ export class JsonRpcTransportError extends Error {
19
+ /** @param {string} message @param {{ cause?: unknown }} [options] */
20
+ constructor(message, options = {}) {
21
+ super(message, { cause: options.cause });
22
+ this.name = "JsonRpcTransportError";
23
+ }
24
+ }
25
+
15
26
  export class JsonRpcDispatchBase {
16
27
  /**
17
28
  * @param {object} options
@@ -5,27 +5,26 @@
5
5
  // on the socket — it speaks WebSocket (RFC 6455) after a standard HTTP/1.1
6
6
  // Upgrade handshake, one JSON-RPC message per text frame. Confirmed live against
7
7
  // codex-cli 0.135.0 (see experiments/native-bridge-feasibility/
8
- // codex-app-server-uds-probe.mjs). This is the UDS sibling of the stdio
9
- // `JsonRpcStdioClient`: same public surface (request/notify/onNotification/
10
- // close/isOpen), different framing.
8
+ // codex-app-server-uds-smoke.mjs). Public surface: request/notify/
9
+ // onNotification/close/isOpen.
11
10
  //
12
11
  // Wire framing notes:
13
12
  // - client -> server frames MUST be masked (RFC 6455 §5.3).
14
13
  // - server -> client frames are unmasked.
15
14
  // - one JSON-RPC object per text frame; fragmented frames are reassembled.
16
15
  // - outbound JSON-RPC omits the `"jsonrpc":"2.0"` header (OpenAI App Server
17
- // JSONL variant), matching JsonRpcStdioClient.
16
+ // JSONL variant).
18
17
  //
19
18
  // Zero new dependencies — minimal hand-rolled WS client (no `ws` package).
20
19
 
21
20
  import { createHash, randomBytes } from "node:crypto";
22
21
  import net from "node:net";
23
22
 
24
- import { JsonRpcDispatchBase } from "./jsonrpc-core.mjs";
25
23
  import {
24
+ JsonRpcDispatchBase,
26
25
  JsonRpcProtocolError,
27
26
  JsonRpcTransportError,
28
- } from "./jsonrpc-stdio.mjs";
27
+ } from "./jsonrpc-core.mjs";
29
28
 
30
29
  const WS_GUID = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
31
30
  const DEFAULT_MAX_FRAME_SIZE = 16 * 1024 * 1024; // 16 MiB
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@triflux/remote",
3
- "version": "10.51.0",
4
- "description": "triflux remote — team mode, psmux, MCP workers, SQLite store.",
3
+ "version": "10.53.0",
4
+ "description": "triflux remote — team mode, psmux, MCP workers.",
5
5
  "type": "module",
6
6
  "main": "hub/index.mjs",
7
7
  "exports": {
@@ -15,12 +15,7 @@
15
15
  "@triflux/core": "^10.0.0-alpha.1"
16
16
  },
17
17
  "dependencies": {
18
- "@modelcontextprotocol/sdk": "^1.27.1",
19
- "ajv": "^8.18.0",
20
- "better-sqlite3": "^12.10.0",
21
- "pino": "^10.3.1",
22
- "pino-pretty": "^13.1.3",
23
- "zod": "^4.0.0"
18
+ "@modelcontextprotocol/sdk": "^1.27.1"
24
19
  },
25
20
  "files": [
26
21
  "hub",
@@ -12,168 +12,126 @@ const policy = {
12
12
  executor: {
13
13
  profile: "gpt61_sol_high",
14
14
  timeoutSec: 1080,
15
- runMode: "fg",
16
- opusOversight: false,
17
15
  mcpHint: "implement",
18
16
  subcommand: "exec",
19
17
  },
20
18
  codex: {
21
19
  profile: "gpt61_sol_high",
22
20
  timeoutSec: 1080,
23
- runMode: "fg",
24
- opusOversight: false,
25
21
  mcpHint: "implement",
26
22
  subcommand: "exec",
27
23
  },
28
24
  "build-fixer": {
29
25
  profile: "gpt6_luna_high",
30
26
  timeoutSec: 540,
31
- runMode: "fg",
32
- opusOversight: false,
33
27
  mcpHint: "implement",
34
28
  subcommand: "exec",
35
29
  },
36
30
  cleanup: {
37
31
  profile: "gpt61_sol_med",
38
32
  timeoutSec: 540,
39
- runMode: "fg",
40
- opusOversight: false,
41
33
  mcpHint: "implement",
42
34
  subcommand: "exec",
43
35
  },
44
36
  deslop: {
45
37
  profile: "gpt61_sol_med",
46
38
  timeoutSec: 540,
47
- runMode: "fg",
48
- opusOversight: false,
49
39
  mcpHint: "implement",
50
40
  subcommand: "exec",
51
41
  },
52
42
  debugger: {
53
43
  profile: "gpt6_astra_xhigh",
54
44
  timeoutSec: 900,
55
- runMode: "bg",
56
- opusOversight: false,
57
45
  mcpHint: "implement",
58
46
  subcommand: "exec",
59
47
  },
60
48
  "deep-executor": {
61
49
  profile: "gpt6_astra_xhigh",
62
50
  timeoutSec: 3600,
63
- runMode: "bg",
64
- opusOversight: true,
65
51
  mcpHint: "implement",
66
52
  subcommand: "exec",
67
53
  },
68
54
  architect: {
69
55
  profile: "gpt6_astra_xhigh",
70
56
  timeoutSec: 3600,
71
- runMode: "bg",
72
- opusOversight: true,
73
57
  mcpHint: "analyze",
74
58
  subcommand: "exec",
75
59
  },
76
60
  critic: {
77
61
  profile: "gpt6_astra_xhigh",
78
62
  timeoutSec: 3600,
79
- runMode: "bg",
80
- opusOversight: true,
81
63
  mcpHint: "analyze",
82
64
  subcommand: "exec",
83
65
  },
84
66
  planner: {
85
67
  profile: "gpt6_astra_xhigh",
86
68
  timeoutSec: 3600,
87
- runMode: "fg",
88
- opusOversight: true,
89
69
  mcpHint: "analyze",
90
70
  subcommand: "exec",
91
71
  },
92
72
  analyst: {
93
73
  profile: "gpt6_astra_xhigh",
94
74
  timeoutSec: 3600,
95
- runMode: "fg",
96
- opusOversight: true,
97
75
  mcpHint: "analyze",
98
76
  subcommand: "exec",
99
77
  },
100
78
  "code-reviewer": {
101
79
  profile: "gpt61_sol_high",
102
80
  timeoutSec: 1800,
103
- runMode: "bg",
104
- opusOversight: false,
105
81
  mcpHint: "review",
106
82
  subcommand: "review",
107
83
  },
108
84
  "quality-reviewer": {
109
85
  profile: "gpt61_sol_high",
110
86
  timeoutSec: 1800,
111
- runMode: "bg",
112
- opusOversight: false,
113
87
  mcpHint: "review",
114
88
  subcommand: "review",
115
89
  },
116
90
  "security-reviewer": {
117
91
  profile: "gpt6_astra_xhigh",
118
92
  timeoutSec: 1800,
119
- runMode: "bg",
120
- opusOversight: true,
121
93
  mcpHint: "review",
122
94
  subcommand: "review",
123
95
  },
124
96
  scientist: {
125
97
  profile: "gpt61_sol_high",
126
98
  timeoutSec: 1440,
127
- runMode: "bg",
128
- opusOversight: false,
129
99
  mcpHint: "analyze",
130
100
  subcommand: "exec",
131
101
  },
132
102
  "document-specialist": {
133
103
  profile: "gpt61_sol_high",
134
104
  timeoutSec: 1440,
135
- runMode: "bg",
136
- opusOversight: false,
137
105
  mcpHint: "analyze",
138
106
  subcommand: "exec",
139
107
  },
140
108
  "scientist-deep": {
141
109
  profile: "gpt6_astra_xhigh",
142
110
  timeoutSec: 3600,
143
- runMode: "bg",
144
- opusOversight: false,
145
111
  mcpHint: "analyze",
146
112
  subcommand: "exec",
147
113
  },
148
114
  verifier: {
149
115
  profile: "gpt61_sol_high",
150
116
  timeoutSec: 1200,
151
- runMode: "fg",
152
- opusOversight: false,
153
117
  mcpHint: "review",
154
118
  subcommand: "review",
155
119
  },
156
120
  "test-engineer": {
157
121
  profile: "gpt61_sol_high",
158
122
  timeoutSec: 1200,
159
- runMode: "bg",
160
- opusOversight: false,
161
123
  mcpHint: "implement",
162
124
  subcommand: "exec",
163
125
  },
164
126
  "qa-tester": {
165
127
  profile: "gpt61_sol_high",
166
128
  timeoutSec: 1200,
167
- runMode: "bg",
168
- opusOversight: false,
169
129
  mcpHint: "review",
170
130
  subcommand: "review",
171
131
  },
172
132
  spark: {
173
133
  profile: "gpt6_luna_low",
174
134
  timeoutSec: 180,
175
- runMode: "fg",
176
- opusOversight: false,
177
135
  mcpHint: "implement",
178
136
  subcommand: "exec",
179
137
  },
@@ -182,16 +140,12 @@ const policy = {
182
140
  designer: {
183
141
  profile: "gpt6_astra_xhigh",
184
142
  timeoutSec: 900,
185
- runMode: "bg",
186
- opusOversight: false,
187
143
  mcpHint: "implement",
188
144
  subcommand: "exec",
189
145
  },
190
146
  writer: {
191
147
  profile: "gpt6_luna_high",
192
148
  timeoutSec: 900,
193
- runMode: "bg",
194
- opusOversight: false,
195
149
  mcpHint: "implement",
196
150
  subcommand: "exec",
197
151
  },
@@ -319,22 +273,6 @@ export function resolveNestedCodexAgentProfile(
319
273
  return effort.toLowerCase() === "ultra" ? "gpt6_astra_max" : candidate;
320
274
  }
321
275
 
322
- const MIN_TIMEOUT_BY_AGENT = Object.freeze({
323
- "deep-executor": 900,
324
- architect: 900,
325
- planner: 900,
326
- critic: 900,
327
- analyst: 900,
328
- "document-specialist": 900,
329
- scientist: 900,
330
- "scientist-deep": 900,
331
- "code-reviewer": 600,
332
- "security-reviewer": 600,
333
- "quality-reviewer": 600,
334
- executor: 300,
335
- debugger: 300,
336
- });
337
-
338
276
  const EXPECTED_DURATION_BY_AGENT = Object.freeze({
339
277
  writer: 90,
340
278
  verifier: 90,
@@ -409,14 +347,11 @@ export function resolveAgentRoute(
409
347
  provider,
410
348
  policy.profile,
411
349
  policy.timeoutSec,
412
- policy.runMode,
413
- policy.opusOversight,
414
350
  policy.mcpHint,
415
351
  policy.subcommand,
416
352
  normalizedOverride,
417
353
  resolvedOverride,
418
354
  geminiProfileResolver(agent),
419
- MIN_TIMEOUT_BY_AGENT[agent] ?? 120,
420
355
  EXPECTED_DURATION_BY_AGENT[agent] ?? 30,
421
356
  NATIVE_CODEX_AGENTS.has(agent),
422
357
  ];
@@ -495,8 +430,6 @@ async function runCli() {
495
430
  [
496
431
  resolved.profile,
497
432
  resolved.timeoutSec,
498
- resolved.runMode,
499
- resolved.opusOversight,
500
433
  resolved.mcpHint,
501
434
  resolved.subcommand,
502
435
  ].join("\t"),
@@ -12,32 +12,22 @@ export const command = null;
12
12
  const AGENT_PROFILES = {
13
13
  explore: {
14
14
  timeoutSec: 600,
15
- runMode: "fg",
16
- opusOversight: false,
17
15
  model: "haiku",
18
16
  },
19
17
  claude: {
20
18
  timeoutSec: 600,
21
- runMode: "fg",
22
- opusOversight: false,
23
19
  model: "haiku",
24
20
  },
25
21
  "test-engineer": {
26
22
  timeoutSec: 1200,
27
- runMode: "bg",
28
- opusOversight: false,
29
23
  model: "sonnet",
30
24
  },
31
25
  "qa-tester": {
32
26
  timeoutSec: 1200,
33
- runMode: "bg",
34
- opusOversight: false,
35
27
  model: "sonnet",
36
28
  },
37
29
  verifier: {
38
30
  timeoutSec: 1200,
39
- runMode: "fg",
40
- opusOversight: false,
41
31
  model: "sonnet",
42
32
  },
43
33
  };
@@ -62,8 +52,6 @@ export function plan({
62
52
  profile: "claude-native",
63
53
  effort: "n/a",
64
54
  timeoutMs: effectiveTimeoutSec * 1000,
65
- runMode: cfg.runMode,
66
- opusOversight: cfg.opusOversight,
67
55
  model: cfg.model,
68
56
  mcpProfile: mcpProfile === "auto" ? null : mcpProfile,
69
57
  promptLength: prompt.length,
@@ -1,63 +1,12 @@
1
- import { execSync } from "node:child_process";
2
1
  import { createHash } from "node:crypto";
3
2
  import { existsSync, readFileSync } from "node:fs";
4
3
  import { homedir } from "node:os";
5
4
  import { join } from "node:path";
6
- import { resolveHubPortForContext } from "../../hub/hub-lifecycle.mjs";
7
5
  import { whichCommand, whichCommandAsync } from "@triflux/core/hub/platform.mjs";
8
6
 
9
- const HUB_DEFAULT_PORT = 27888;
10
7
  const CLI_PROBE_CACHE = new Map();
11
8
  const CLI_PROBE_PROMISES = new Map();
12
9
 
13
- function fetchHubStatus({
14
- execSyncFn = execSync,
15
- statusUrl = resolveDefaultStatusUrl(),
16
- timeout = 3000,
17
- } = {}) {
18
- const response = execSyncFn(`curl -sf ${statusUrl}`, {
19
- timeout,
20
- encoding: "utf8",
21
- windowsHide: true,
22
- });
23
- const data = JSON.parse(response);
24
- return {
25
- ok: true,
26
- state: data?.hub?.state || "unknown",
27
- pid: data?.pid,
28
- };
29
- }
30
-
31
- function resolveDefaultStatusUrl(env = process.env, cwd = process.cwd()) {
32
- const port = resolveHubPortForContext({
33
- env,
34
- cwd,
35
- defaultPort: HUB_DEFAULT_PORT,
36
- });
37
- return `http://127.0.0.1:${port}/status`;
38
- }
39
-
40
- function resolveStatusUrlForContext({
41
- statusUrl,
42
- env = process.env,
43
- cwd = process.cwd(),
44
- } = {}) {
45
- try {
46
- const url = new URL(String(statusUrl));
47
- url.port = String(
48
- resolveHubPortForContext({
49
- port: url.port,
50
- env,
51
- cwd,
52
- defaultPort: HUB_DEFAULT_PORT,
53
- }),
54
- );
55
- return url.toString();
56
- } catch {
57
- return resolveDefaultStatusUrl(env, cwd);
58
- }
59
- }
60
-
61
10
  function normalizeCliName(name) {
62
11
  return String(name ?? "").trim() || null;
63
12
  }
@@ -219,22 +168,3 @@ export function detectCodexPlan(options = {}) {
219
168
  const { plan, source } = detectCodexAuthState(options);
220
169
  return { plan, source };
221
170
  }
222
-
223
- export function checkHub({
224
- env = process.env,
225
- cwd = process.cwd(),
226
- statusUrl = resolveDefaultStatusUrl(env, cwd),
227
- requestTimeoutMs = 3000,
228
- execSyncFn = execSync,
229
- } = {}) {
230
- const guardedStatusUrl = resolveStatusUrlForContext({ statusUrl, env, cwd });
231
- try {
232
- return fetchHubStatus({
233
- execSyncFn,
234
- statusUrl: guardedStatusUrl,
235
- timeout: requestTimeoutMs,
236
- });
237
- } catch {
238
- return { ok: false, state: "unreachable", restart: "disabled" };
239
- }
240
- }