@sleep2agi/agent-network 2.3.0-preview.15 → 2.3.0-preview.150

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 (156) hide show
  1. package/README.md +35 -324
  2. package/dist/bin/anet.cjs +101 -0
  3. package/dist/bin/cli.d.ts +1 -0
  4. package/dist/bin/cli.js +20 -1
  5. package/dist/bin/goal-wake-log-render.d.ts +31 -0
  6. package/dist/src/active-network-task.d.ts +28 -0
  7. package/dist/src/batch-workdir.d.ts +9 -0
  8. package/dist/src/bootstrap-password-db.d.ts +13 -0
  9. package/dist/src/channel-attachments.d.ts +29 -0
  10. package/dist/src/channel-inbox-wake.d.ts +21 -0
  11. package/dist/src/channel-meta.d.ts +10 -0
  12. package/dist/src/channel-peer-reply.d.ts +41 -0
  13. package/dist/src/channel-task-trace.d.ts +14 -0
  14. package/dist/src/claude-vendor-env.d.ts +28 -0
  15. package/dist/src/cli-args.d.ts +8 -0
  16. package/dist/src/cli-auth-session.d.ts +47 -0
  17. package/dist/src/cli-errors.d.ts +39 -0
  18. package/dist/src/cli-exit.d.ts +11 -0
  19. package/dist/src/cli-help.d.ts +10 -0
  20. package/dist/src/cli-version-display.d.ts +16 -0
  21. package/dist/src/client-task-trace.d.ts +9 -0
  22. package/dist/src/client.js +1 -1
  23. package/dist/src/codex-adopt.d.ts +46 -0
  24. package/dist/src/codex-auth-fingerprint.d.ts +211 -0
  25. package/dist/src/codex-copresence-bridge-log.d.ts +44 -0
  26. package/dist/src/codex-copresence-login-gate.d.ts +16 -0
  27. package/dist/src/codex-copresence-model.d.ts +23 -0
  28. package/dist/src/codex-copresence-preflight.d.ts +65 -0
  29. package/dist/src/codex-copresence-profile.d.ts +125 -0
  30. package/dist/src/codex-copresence-recovery.d.ts +58 -0
  31. package/dist/src/codex-copresence-thread.d.ts +13 -0
  32. package/dist/src/codex-external-appserver.d.ts +120 -0
  33. package/dist/src/codex-home-enforce.d.ts +88 -0
  34. package/dist/src/codex-lifecycle-account.d.ts +104 -0
  35. package/dist/src/codex-lifecycle-canary.d.ts +20 -0
  36. package/dist/src/codex-lifecycle-facts.d.ts +53 -0
  37. package/dist/src/codex-lifecycle-fork.d.ts +91 -0
  38. package/dist/src/codex-lifecycle-preflight.d.ts +77 -0
  39. package/dist/src/codex-lifecycle-receipt.d.ts +53 -0
  40. package/dist/src/codex-lifecycle-restart.d.ts +88 -0
  41. package/dist/src/codex-login-share-guard.d.ts +146 -0
  42. package/dist/src/codex-menu.d.ts +99 -0
  43. package/dist/src/codex-model-default.d.ts +6 -0
  44. package/dist/src/codex-node-login.d.ts +98 -0
  45. package/dist/src/codex-pending-thread-restart.d.ts +55 -0
  46. package/dist/src/codex-resume.d.ts +89 -0
  47. package/dist/src/codex-tui-client-health.d.ts +30 -0
  48. package/dist/src/commhub-response.d.ts +1 -0
  49. package/dist/src/controlled-upload.d.ts +83 -0
  50. package/dist/src/copresence-deps.d.ts +22 -0
  51. package/dist/src/copresence-identity.d.ts +363 -0
  52. package/dist/src/copresence-startup-diagnosis.d.ts +17 -0
  53. package/dist/src/daemon-anet-bin.d.ts +32 -0
  54. package/dist/src/daemon-capability-display.d.ts +110 -0
  55. package/dist/src/daemon-capability-display.js +21 -0
  56. package/dist/src/daemon-inherited-env.d.ts +9 -0
  57. package/dist/src/daemon-runtime-path-preflight.d.ts +22 -0
  58. package/dist/src/daemon-runtime-staleness.d.ts +13 -0
  59. package/dist/src/dashboard-managed-process.d.ts +35 -0
  60. package/dist/src/display-width.d.ts +27 -0
  61. package/dist/src/doctor-node-count.d.ts +28 -0
  62. package/dist/src/environ-alias.d.ts +14 -0
  63. package/dist/src/grok-attach-client.d.ts +129 -0
  64. package/dist/src/grok-build-drift.d.ts +15 -0
  65. package/dist/src/grok-copresence-disclosure.d.ts +11 -0
  66. package/dist/src/grok-copresence-orchestration.d.ts +75 -0
  67. package/dist/src/grok-copresence-profile.d.ts +65 -0
  68. package/dist/src/grok-create-mode.d.ts +19 -0
  69. package/dist/src/host-telemetry.d.ts +14 -0
  70. package/dist/src/hub-health-timeout.d.ts +4 -0
  71. package/dist/src/hub-server-version.d.ts +64 -0
  72. package/dist/src/hub-stop.d.ts +74 -0
  73. package/dist/src/hub-time-display.d.ts +20 -0
  74. package/dist/src/hub-version-skew.d.ts +19 -0
  75. package/dist/src/im/correlation-store.d.ts +34 -0
  76. package/dist/src/im/feishu/adapter.d.ts +54 -0
  77. package/dist/src/im/feishu/bridge.d.ts +78 -14
  78. package/dist/src/im/feishu/hub-upload.d.ts +88 -0
  79. package/dist/src/im/feishu/outbound-route.d.ts +62 -0
  80. package/dist/src/im/feishu/worker-lifecycle.d.ts +13 -0
  81. package/dist/src/im/feishu/worker.js +182 -143
  82. package/dist/src/im/types.d.ts +30 -1
  83. package/dist/src/inbox-drain.d.ts +20 -0
  84. package/dist/src/local-process-state.d.ts +12 -0
  85. package/dist/src/locale-diagnostic.d.ts +12 -0
  86. package/dist/src/login-client-label.d.ts +6 -0
  87. package/dist/src/ls-columns.d.ts +15 -0
  88. package/dist/src/mock-llm.d.ts +12 -0
  89. package/dist/src/node-activity-log.d.ts +4 -0
  90. package/dist/src/node-clone.d.ts +134 -0
  91. package/dist/src/node-delete-hub.d.ts +42 -0
  92. package/dist/src/node-files.d.ts +62 -0
  93. package/dist/src/node-locate.d.ts +60 -0
  94. package/dist/src/node-ls-all.d.ts +80 -0
  95. package/dist/src/node-menu.d.ts +40 -0
  96. package/dist/src/node-not-found.d.ts +1 -0
  97. package/dist/src/node-remote.d.ts +180 -0
  98. package/dist/src/node-running-guard.d.ts +9 -0
  99. package/dist/src/node-server-identity.d.ts +35 -0
  100. package/dist/src/node-server-payload.d.ts +66 -0
  101. package/dist/src/node-server-rules-file.d.ts +14 -0
  102. package/dist/src/node-server-version.d.ts +39 -0
  103. package/dist/src/node-server.js +8 -1
  104. package/dist/src/node-skills.d.ts +32 -0
  105. package/dist/src/normalize-runtime.d.ts +29 -2
  106. package/dist/src/offline-age.d.ts +29 -0
  107. package/dist/src/one-line-cell.d.ts +20 -0
  108. package/dist/src/opencode-agent-node-pair.d.ts +25 -0
  109. package/dist/src/opencode-auth-login.d.ts +43 -0
  110. package/dist/src/opencode-free-tier.d.ts +27 -0
  111. package/dist/src/opencode-generation-create.d.ts +27 -0
  112. package/dist/src/opencode-generation-record.d.ts +24 -0
  113. package/dist/src/opencode-launch-env.d.ts +13 -0
  114. package/dist/src/opencode-owner-mode.d.ts +6 -0
  115. package/dist/src/opencode-package-binary.d.ts +44 -0
  116. package/dist/src/opencode-pin.d.ts +61 -0
  117. package/dist/src/opencode-preset.d.ts +73 -0
  118. package/dist/src/opencode-runtime-binding.d.ts +30 -0
  119. package/dist/src/opencode-safe-root.d.ts +36 -0
  120. package/dist/src/opencode-smoke-env.d.ts +1 -0
  121. package/dist/src/opencode-versions.d.ts +44 -0
  122. package/dist/src/outbound-attachments.d.ts +60 -0
  123. package/dist/src/outbound-tool-names.d.ts +1 -0
  124. package/dist/src/owned-roots.d.ts +58 -0
  125. package/dist/src/owner-env-file.d.ts +2 -0
  126. package/dist/src/package-mode-preflight.d.ts +41 -0
  127. package/dist/src/posix-codex-copresence.d.ts +35 -0
  128. package/dist/src/posix-modes.d.ts +36 -0
  129. package/dist/src/primary-network.d.ts +23 -0
  130. package/dist/src/private-state.d.ts +10 -0
  131. package/dist/src/process-telemetry.d.ts +12 -0
  132. package/dist/src/profile-serialize.d.ts +1 -0
  133. package/dist/src/project-key.d.ts +1 -0
  134. package/dist/src/reply-local-links.d.ts +47 -0
  135. package/dist/src/reply-originator.d.ts +20 -0
  136. package/dist/src/resume-runtime-infer.d.ts +18 -0
  137. package/dist/src/rules-file.d.ts +53 -0
  138. package/dist/src/secret-shell-guidance.d.ts +4 -0
  139. package/dist/src/session-status-class.d.ts +48 -0
  140. package/dist/src/sibling-agent-node.d.ts +23 -0
  141. package/dist/src/stale-socket.d.ts +118 -0
  142. package/dist/src/subcommand-redirect.d.ts +26 -0
  143. package/dist/src/task-trace.d.ts +33 -0
  144. package/dist/src/tmux-attach.d.ts +11 -0
  145. package/dist/src/tmux-capability.d.ts +58 -0
  146. package/dist/src/tmux-exact-target.d.ts +36 -0
  147. package/dist/src/tmux-format.d.ts +20 -0
  148. package/dist/src/tmux-pane-prompt.d.ts +22 -0
  149. package/dist/src/tmux.d.ts +44 -0
  150. package/dist/src/token-cli.d.ts +13 -0
  151. package/dist/src/tool-allowlist.d.ts +28 -0
  152. package/dist/src/unsafe-package-path-reason.d.ts +31 -0
  153. package/dist/src/upgrade-channel.d.ts +31 -0
  154. package/dist/src/win-launcher.d.ts +20 -0
  155. package/dist/src/windows-codex-copresence.d.ts +60 -0
  156. package/package.json +11 -6
@@ -0,0 +1,9 @@
1
+ export declare function isInheritedSessionIdentityEnvName(name: string): boolean;
2
+ /** Return a copy of `env` without session-identity variables, plus the sorted
3
+ * list of names that were removed. Does not mutate `env`. */
4
+ export declare function scrubInheritedSessionIdentityEnv(env: NodeJS.ProcessEnv): {
5
+ env: NodeJS.ProcessEnv;
6
+ removed: string[];
7
+ };
8
+ /** One log line, names only. */
9
+ export declare function formatScrubbedEnvLine(removed: string[]): string;
@@ -0,0 +1,22 @@
1
+ /** 一个 runtime 依赖的外部二进制,以及它**有据可查**的安装位置。 */
2
+ export type RuntimeBinaryHint = {
3
+ /** 哪些 runtime 名需要这个二进制 */
4
+ readonly runtimes: readonly string[];
5
+ /** 在 PATH 上查的裸名 */
6
+ readonly binary: string;
7
+ /** 官方安装位置(相对 $HOME) */
8
+ readonly homeRelativeDir: string;
9
+ /** 🔴 这一条的出处 —— 没有出处就不许进这张表 */
10
+ readonly evidence: string;
11
+ };
12
+ export declare const RUNTIME_BINARY_HINTS: readonly RuntimeBinaryHint[];
13
+ export type PathPreflightInput = {
14
+ /** 这台 daemon 声称支持的 runtime */
15
+ readonly runtimes: readonly string[];
16
+ /** 二进制在 daemon 的 PATH 上能不能找到 */
17
+ readonly resolvesOnPath: (binary: string) => boolean;
18
+ /** 二进制在那个已知位置存不存在 */
19
+ readonly existsInHomeDir: (homeRelativeDir: string, binary: string) => boolean;
20
+ };
21
+ /** 返回要打给用户的警告。**没问题时返回空数组** —— 空是常态,不是失败。 */
22
+ export declare function daemonPathWarnings(input: PathPreflightInput): string[];
@@ -0,0 +1,13 @@
1
+ /**
2
+ * daemon 的 `runtimes_supported` 是**写配置那一刻**的支持集快照,之后不会自愈。
3
+ *
4
+ * 🔴 这不是假想的:#1298 (2026-08-28) 把新建 daemon 的默认清单从 3 个放开到
5
+ * `SUPPORTED_RUNTIME_NAMES` 全体,但**它只改了写入路径**。在那之前 init 过的
6
+ * daemon,配置里仍然只有那 3 个,而且没有任何东西会说出这件事 ——
7
+ * 用户在客户端「选服务器」里看到某台机器少几个 runtime,
8
+ * 既不知道为什么,也不知道该做什么。
9
+ *
10
+ * 判据从**分发处**取(`SUPPORTED_RUNTIME_NAMES`),不在这里手写一份清单:
11
+ * 抄一份就意味着它会再漂一次(同 #1728 的教训)。
12
+ */
13
+ export declare function describeStaleRuntimeSupport(declared: readonly string[] | undefined | null, supported: readonly string[], nameHint?: string): string | null;
@@ -0,0 +1,35 @@
1
+ export type DashboardLaunchSource = "npx" | "global";
2
+ export interface DashboardLaunchRecord {
3
+ schema: 1;
4
+ port: number;
5
+ listener_pid: number;
6
+ listener_birth: string;
7
+ source: DashboardLaunchSource;
8
+ source_key: string;
9
+ recorded_at: string;
10
+ }
11
+ export type DashboardListenerDecision = {
12
+ action: "start";
13
+ } | {
14
+ action: "already_running";
15
+ pid: number;
16
+ } | {
17
+ action: "terminate_owned_stale";
18
+ pid: number;
19
+ reason: "unhealthy" | "version_changed";
20
+ } | {
21
+ action: "refuse";
22
+ reason: string;
23
+ };
24
+ export declare function isDashboardProcessCommand(command: string): boolean;
25
+ export declare function decideDashboardListener(input: {
26
+ port: number;
27
+ listenerPids: number[];
28
+ record: DashboardLaunchRecord | null;
29
+ listenerBirth: string | null;
30
+ listenerCommand: string | null;
31
+ desiredSource: DashboardLaunchSource;
32
+ desiredSourceKey: string;
33
+ healthy: boolean;
34
+ }): DashboardListenerDecision;
35
+ export declare function parseDashboardLaunchRecord(value: unknown): DashboardLaunchRecord | null;
@@ -0,0 +1,27 @@
1
+ /**
2
+ * 终端里的**显示列宽** —— CJK 字符占 2 列,而 `String.length` / `padEnd` 只数码元。
3
+ *
4
+ * 🔴 这份知识仓里本来就有,但它只活在**一个测试文件**里
5
+ * (`daemon-capability-display.test.ts` 的 `displayWidth`,2026-08-30 由 macOS 真机
6
+ * 上「合成首行约 99 列、80 列终端折行且折点落在句子中间」催生)。
7
+ * 生产代码没有它,于是所有用 `padEnd` 对齐的表在中文别名下都是歪的。
8
+ *
9
+ * 实测(2026-08-31,`anet node ls` 对着一支全中文别名的军团):
10
+ *
11
+ * NAME RUNTIME STATUS
12
+ * ──────────────────── ────────────── ────────
13
+ * 通信工程马 claude-code-cli idle ← RUNTIME 列起点
14
+ * 通信IM马 claude-code-cli idle ← 不一样
15
+ * 通信SDK牛 codex-sdk idle ← 又不一样
16
+ *
17
+ * `通信工程马`.length 是 5,`padEnd(20)` 补 15 个空格 —— 但它渲染出来是 10 列,
18
+ * 于是这一行实际占 25 列而不是 20。**别名里 CJK 越多,歪得越远。**
19
+ */
20
+ export declare function displayWidth(s: unknown): number;
21
+ /**
22
+ * 按**显示列**右补空格。已经不短于目标宽度时原样返回(与 `padEnd` 一致,不截断)。
23
+ *
24
+ * 🔴 不截断是有意的:截断会引出「截到一半的宽字符」这个新问题,
25
+ * 而调用方要的只是对齐。**一个修对齐的改动不该顺手引入截断语义。**
26
+ */
27
+ export declare function padDisplayEnd(s: unknown, width: number): string;
@@ -0,0 +1,28 @@
1
+ /**
2
+ * `anet doctor` 原先对「本机配置了几个节点」的判定是:
3
+ *
4
+ * check("Nodes configured", ids.length > 0, `${ids.length} node(s)`);
5
+ *
6
+ * 于是 **0 个节点 → ❌**。而一个刚装好、还没建节点的人跑 `anet doctor`,
7
+ * 看到的是:
8
+ *
9
+ * ❌ Nodes configured — 0 node(s)
10
+ * Result: 9 ok, 3 warnings, 2 errors
11
+ *
12
+ * 🔴 「还没有节点」是**全新安装的预期状态**,不是故障。把它报成 error,
13
+ * 等于在新用户的第一次诊断里制造一个假警报 —— 而这条命令存在的意义
14
+ * 正是告诉他「你这台机器现在好不好」。
15
+ *
16
+ * 🔴 但也不能反过来直接判成「一切正常」:同一个 0 对一个**本来有节点**的人
17
+ * 意味着配置目录不见了。doctor 手上只有一个数字,**分不出这两种现实**。
18
+ * 所以这里既不报错也不报好 —— 把两种都说出来,让读的人自己对号,
19
+ * 并给出各自的下一步。
20
+ */
21
+ export type NodeCountLine = {
22
+ ok: true;
23
+ detail: string;
24
+ } | {
25
+ ok: false;
26
+ info: string;
27
+ };
28
+ export declare function nodeCountLine(count: number): NodeCountLine;
@@ -0,0 +1,14 @@
1
+ /** Parse the environ blob (NUL-separated key=val) and return the
2
+ * COMMHUB_ALIAS value if present, else null. Exported for testing. */
3
+ export declare function parseEnvironAlias(environBlob: string): string | null;
4
+ /** Read /proc/<pid>/environ and return the COMMHUB_ALIAS value.
5
+ * Any file-read error (not-a-Linux, permission denied, race with
6
+ * process exit) returns null — caller must not fail-closed on that
7
+ * (the process is stale/gone/inaccessible, not our problem). */
8
+ export declare function readEnvironAlias(pid: number): string | null;
9
+ /** Scan /proc for pids whose COMMHUB_ALIAS env matches any of the
10
+ * target aliases. Linux-only (procfs); returns null on non-Linux or
11
+ * when /proc is unreadable — caller MUST fail-closed on null per
12
+ * the same #180 R2 fail-closed contract as findNodeProcessesByAlias.
13
+ * Self-pid + init (PID 1) are excluded. */
14
+ export declare function findEnvironAliasMatches(aliases: Iterable<string>, selfPid: number): number[] | null;
@@ -0,0 +1,129 @@
1
+ import type { Duplex } from "node:stream";
2
+ export declare const GROK_ATTACH_PROTOCOL = "anet-grok-copresence-attach";
3
+ export declare const GROK_ATTACH_PROTOCOL_VERSION = 1;
4
+ export declare const GROK_ATTACH_DEFAULT_MAX_FRAME_BYTES: number;
5
+ export declare const GROK_ATTACH_DEFAULT_MAX_BUFFER_BYTES: number;
6
+ export declare const GROK_ATTACH_DEFAULT_HANDSHAKE_TIMEOUT_MS = 5000;
7
+ export declare const GROK_ATTACH_DEFAULT_CLOSE_TIMEOUT_MS = 1000;
8
+ export type GrokAttachJsonValue = null | boolean | number | string | GrokAttachJsonValue[] | {
9
+ [key: string]: GrokAttachJsonValue;
10
+ };
11
+ export interface GrokAttachHelloFrame {
12
+ type: "hello";
13
+ protocol: typeof GROK_ATTACH_PROTOCOL;
14
+ version: typeof GROK_ATTACH_PROTOCOL_VERSION;
15
+ alias: string;
16
+ sessionId: string;
17
+ [key: string]: unknown;
18
+ }
19
+ export interface GrokAttachOutputFrame {
20
+ type: "output";
21
+ data: string;
22
+ encoding: "base64";
23
+ }
24
+ export interface GrokAttachStatusFrame {
25
+ type: "status";
26
+ status: GrokAttachJsonValue;
27
+ }
28
+ export interface GrokAttachErrorFrame {
29
+ type: "error";
30
+ code: string;
31
+ message: string;
32
+ fatal: boolean;
33
+ }
34
+ export interface GrokAttachDetachFrame {
35
+ type: "detach";
36
+ }
37
+ export type GrokAttachServerFrame = GrokAttachHelloFrame | GrokAttachOutputFrame | GrokAttachStatusFrame | GrokAttachErrorFrame | GrokAttachDetachFrame;
38
+ export interface GrokAttachInputFrame {
39
+ type: "input";
40
+ data: string;
41
+ encoding: "base64";
42
+ }
43
+ export interface GrokAttachResizeFrame {
44
+ type: "resize";
45
+ cols: number;
46
+ rows: number;
47
+ }
48
+ /** Asks the node to switch models (issue #879); allowed on control connections. */
49
+ export interface GrokAttachSetModelFrame {
50
+ type: "set-model";
51
+ model: string;
52
+ }
53
+ export type GrokAttachClientFrame = GrokAttachInputFrame | GrokAttachResizeFrame | GrokAttachSetModelFrame | GrokAttachDetachFrame;
54
+ export interface GrokAttachInputSource {
55
+ on(event: "data", listener: (chunk: unknown) => void): unknown;
56
+ on(event: "end", listener: () => void): unknown;
57
+ off?(event: "data" | "end", listener: (...args: any[]) => void): unknown;
58
+ removeListener?(event: "data" | "end", listener: (...args: any[]) => void): unknown;
59
+ pause?(): unknown;
60
+ resume?(): unknown;
61
+ }
62
+ export interface GrokAttachOutputSink {
63
+ write(chunk: Uint8Array): boolean | void;
64
+ columns?: number;
65
+ rows?: number;
66
+ once?(event: "drain", listener: () => void): unknown;
67
+ }
68
+ export interface GrokAttachSignalSource {
69
+ on(event: "SIGWINCH", listener: () => void): unknown;
70
+ off?(event: "SIGWINCH", listener: () => void): unknown;
71
+ removeListener?(event: "SIGWINCH", listener: () => void): unknown;
72
+ }
73
+ export interface GrokAttachSocketStat {
74
+ uid: number;
75
+ isSocket(): boolean;
76
+ isSymbolicLink(): boolean;
77
+ }
78
+ export interface GrokAttachDependencies {
79
+ lstat?: (socketPath: string) => Promise<GrokAttachSocketStat>;
80
+ getuid?: () => number | undefined;
81
+ connect?: (socketPath: string) => Duplex;
82
+ }
83
+ export interface GrokAttachClientOptions {
84
+ socketPath: string;
85
+ input: GrokAttachInputSource;
86
+ output: GrokAttachOutputSink;
87
+ signalSource?: GrokAttachSignalSource;
88
+ terminalSize?: () => {
89
+ cols: number | undefined;
90
+ rows: number | undefined;
91
+ };
92
+ maxFrameBytes?: number;
93
+ maxBufferBytes?: number;
94
+ handshakeTimeoutMs?: number;
95
+ closeTimeoutMs?: number;
96
+ detachOnInputEnd?: boolean;
97
+ onHello?: (frame: GrokAttachHelloFrame) => void;
98
+ onStatus?: (frame: GrokAttachStatusFrame) => void;
99
+ onError?: (error: Error, frame?: GrokAttachErrorFrame) => void;
100
+ onDetach?: (frame: GrokAttachDetachFrame) => void;
101
+ dependencies?: GrokAttachDependencies;
102
+ }
103
+ export type GrokAttachCloseReason = "local-detach" | "input-end" | "remote-detach" | "socket-close" | "socket-error" | "protocol-error";
104
+ export interface GrokAttachCloseInfo {
105
+ reason: GrokAttachCloseReason;
106
+ error?: Error;
107
+ }
108
+ export interface GrokAttachSession {
109
+ readonly socketPath: string;
110
+ readonly closed: Promise<GrokAttachCloseInfo>;
111
+ detach(): void;
112
+ resize(cols?: number, rows?: number): void;
113
+ /**
114
+ * Ask the node to switch models (issue #879).
115
+ *
116
+ * The outcome does not come back from this call — it arrives as a `status`
117
+ * frame carrying `modelSwitch`, because the node may accept, refuse
118
+ * (busy / unchanged / invalid), or fail while re-spawning. Callers read it
119
+ * through `onStatus`.
120
+ */
121
+ setModel(model: string): void;
122
+ }
123
+ export declare class GrokAttachRemoteError extends Error {
124
+ readonly code: string;
125
+ readonly fatal: boolean;
126
+ constructor(frame: GrokAttachErrorFrame);
127
+ }
128
+ export declare function validateGrokAttachSocket(socketPath: string, dependencies?: GrokAttachDependencies): Promise<void>;
129
+ export declare function connectGrokAttach(options: GrokAttachClientOptions): Promise<GrokAttachSession>;
@@ -0,0 +1,15 @@
1
+ /** 从一段日志文本里取出**最后一次**出现的 grok 版本串。
2
+ * 🔴 取最后一次,不是第一次:日志按时间追加,最后一次才是这个进程最近一次
3
+ * 启动时用的那个。取第一次会在日志轮转/多次重启后指向历史。 */
4
+ export declare function parseGrokBuildFromLog(text: string): string | undefined;
5
+ /** 从 `grok --version` 的输出里取版本串(同一形状)。 */
6
+ export declare function parseGrokBuildFromVersionOutput(out: string): string | undefined;
7
+ export type GrokBuildDriftKind = "match" | "drift" | "unknown-current" | "unknown-started";
8
+ export interface GrokBuildDrift {
9
+ readonly kind: GrokBuildDriftKind;
10
+ readonly started?: string;
11
+ readonly current?: string;
12
+ /** 一句人读的话。四种 kind 四句不同的话 —— 含糊化等于把这一格的功能删掉。 */
13
+ readonly line: string;
14
+ }
15
+ export declare function describeGrokBuildDrift(started: string | undefined, current: string | undefined): GrokBuildDrift;
@@ -0,0 +1,11 @@
1
+ export type GrokCopresenceSessionDisclosure = "configured" | "new" | "resume";
2
+ export type GrokCopresenceDisclosure = {
3
+ profile: "commhub-only" | "x-search" | "repo-read" | "invalid";
4
+ lines: readonly string[];
5
+ };
6
+ /**
7
+ * Describe only the exact tool profiles accepted by the pinned Grok TUI
8
+ * runtime. This is deliberately exact: a near-miss must never be presented as
9
+ * either reviewed capability set.
10
+ */
11
+ export declare function grokCopresenceDisclosure(tools: unknown, session?: GrokCopresenceSessionDisclosure): GrokCopresenceDisclosure;
@@ -0,0 +1,75 @@
1
+ /** tmux session names. The attachable TUI owns the bare alias so that
2
+ * `tmux attach -t '=<alias>'` lands a human on the TUI, matching the codex
3
+ * lane exactly — an operator should not have to remember which runtime a node
4
+ * uses in order to know where to attach. */
5
+ export declare function grokCopresenceSessions(displayName: string): {
6
+ node: string;
7
+ tui: string;
8
+ };
9
+ export type GrokAttachSocketState = "missing" | "not_a_socket" | "ready";
10
+ /** Readiness is "the attach socket exists AND is a socket", never "the child
11
+ * process started". A grok leader that dies during startup leaves either no
12
+ * socket at all or a stale regular file from an aborted run; both used to read
13
+ * as ready because nothing looked. */
14
+ export declare function grokAttachSocketState(entry: {
15
+ isSocket(): boolean;
16
+ } | null | undefined): GrokAttachSocketState;
17
+ /** Set on the node child so that `anet node start` inside the tmux session does
18
+ * not re-enter this orchestration and fork bomb. The codex lane guards on the
19
+ * same variable (cli.ts: `process.env.ANET_COPRESENCE_BRIDGE !== "1"`); using a
20
+ * second name would leave two guards that must be kept in sync by hand. */
21
+ export declare const GROK_COPRESENCE_CHILD_ENV = "ANET_COPRESENCE_BRIDGE";
22
+ export interface GrokCopresenceDiagnosis {
23
+ readonly ok: boolean;
24
+ readonly lines: readonly string[];
25
+ /** #1768 —— 非阻断提示:平台能跑,但 agent-node 的能力表说它少了内核层保证。
26
+ * ok=true 时也可能非空;调用方打印它,不退出。 */
27
+ readonly notices: readonly string[];
28
+ }
29
+ /** One block naming every reason this node cannot run the shared TUI, not one
30
+ * exit per reason. A node that is both the wrong runtime AND missing its
31
+ * attach socket should learn both in one run. */
32
+ /** Platforms whose PTY / IPC / isolation primitives the grok co-presence lane
33
+ * has actually been validated on. agent-node refuses anywhere else, and it does
34
+ * so only after the node has been created and started once:
35
+ *
36
+ * [agent-node] grok-build-cli co-presence 无法在 darwin 上运行,缺少:
37
+ * 平台 darwin 尚未验证过共存所需的 PTY / IPC / 隔离原语
38
+ *
39
+ * Learned the expensive way on a Mac mini: install anet, install agent-node,
40
+ * create the node, start it — and only then find out the platform is refused.
41
+ * A one-command launcher that lets someone get that far has not saved them
42
+ * anything, so say it in the same breath as every other gap. */
43
+ export declare const GROK_COPRESENCE_PLATFORMS: readonly NodeJS.Platform[];
44
+ /** 能跑但没有内核层强制的平台 —— agent-node 启动时逐条打印 reducedGuarantees,这里只提前说一句。 */
45
+ export declare const GROK_COPRESENCE_REDUCED_GUARANTEE_PLATFORMS: readonly NodeJS.Platform[];
46
+ export declare function diagnoseGrokCopresence(input: {
47
+ runtime: string;
48
+ displayName: string;
49
+ grokCopresence?: boolean;
50
+ grokAttachSocket?: string;
51
+ platform?: NodeJS.Platform;
52
+ }): GrokCopresenceDiagnosis;
53
+ /** True when a plain `anet node start <name>` (no flag) should bring the shared
54
+ * TUI up by itself.
55
+ *
56
+ * 🔴 Deliberately NOT keyed on `grokCopresence`. That field is set to true at
57
+ * CREATE time for every grok-build-cli node, so reading it here would silently
58
+ * change what `anet node start` does for every grok node that already exists —
59
+ * they would stop running in the foreground and fork into tmux, unasked. Caught
60
+ * exactly that way: a start without the flag entered the orchestration.
61
+ *
62
+ * The codex lane looks the same but is not: `codexCopresence` is written only
63
+ * when the operator passes the flag. So grok needs its own record of the
64
+ * operator's choice, and `grokCopresenceAuto` is it. */
65
+ export declare function grokCopresenceRequested(flagPassed: boolean, profile: {
66
+ runtime?: unknown;
67
+ grokCopresence?: unknown;
68
+ grokCopresenceAuto?: unknown;
69
+ }): boolean;
70
+ /** Record the operator's opt-in so the NEXT start needs no flag — and only then.
71
+ * Never infer it from `grokCopresence`, which create sets by default. */
72
+ export declare function shouldPersistGrokCopresence(flagPassed: boolean, profile: {
73
+ runtime?: unknown;
74
+ grokCopresenceAuto?: unknown;
75
+ }): boolean;
@@ -0,0 +1,65 @@
1
+ export declare const GROK_UNIX_SOCKET_PATH_MAX_BYTES = 100;
2
+ export declare const GROK_COPRESENCE_CAPABILITY_MARKER = "ANET_CAPABILITY_GROK_COPRESENCE_V2";
3
+ export declare const GROK_PREVIEW_RESOLVER_INHERITED_ENV_KEYS: readonly ["PATH", "TMPDIR", "TMP", "TEMP", "LANG", "LC_ALL", "LC_CTYPE", "TZ"];
4
+ export declare const GROK_AGENT_NODE_INHERITED_ENV_KEYS: readonly ["PATH", "HOME", "TMPDIR", "TMP", "TEMP", "LANG", "LC_ALL", "LC_CTYPE", "TZ", "SHELL", "USER", "LOGNAME", "TERM", "COLORTERM", "NO_COLOR"];
5
+ export declare const GROK_AGENT_NODE_OPTIONAL_ENV_KEYS: readonly ["GROK_BINARY", "GROK_HOME", "FLOCK_BINARY", "SETPRIV_BINARY", "UNSHARE_BINARY", "GROK_CLI_TIMEOUT_MS", "GROK_HANDSHAKE_TIMEOUT_MS", "LOG_LEVEL", "ANET_GOAL_TICK_MS", "COMMHUB_MAX_GOALS_PER_NODE"];
6
+ /** Exact environment for the long-lived agent-node parent of the Grok TUI. */
7
+ export declare function buildGrokAgentNodeEnv(parentEnv: NodeJS.ProcessEnv): Record<string, string>;
8
+ export declare function grokPreviewResolverConfigPaths(home: string): {
9
+ directory: string;
10
+ userConfig: string;
11
+ globalConfig: string;
12
+ };
13
+ /**
14
+ * npm rejects loading the same file as both user and global config. Prepare
15
+ * two distinct, empty, owner-only files without following a final symlink so
16
+ * the resolver cannot inherit a user's ordinary npmrc credentials.
17
+ */
18
+ export declare function prepareGrokPreviewResolverConfigs(home: string): void;
19
+ /** Exact environment for the short-lived npm resolver and capability probe. */
20
+ export declare function buildGrokPreviewResolverEnv(parentEnv: NodeJS.ProcessEnv, home: string): Record<string, string>;
21
+ /** Old headless-only agent-node builds already advertised grok-build-cli. */
22
+ export declare function agentNodeHelpSupportsGrokCopresence(help: string): boolean;
23
+ export interface GrokCopresenceProfileFields {
24
+ grokCopresence: boolean;
25
+ grokLeaderSocket?: string;
26
+ grokAttachSocket?: string;
27
+ }
28
+ export interface GrokSocketPathOptions {
29
+ cwd?: string;
30
+ home?: string;
31
+ xdgRuntimeDir?: string;
32
+ uid?: number;
33
+ platform?: NodeJS.Platform;
34
+ }
35
+ /**
36
+ * Allocate deterministic Unix socket paths without creating anything.
37
+ *
38
+ * Grok's workspace sandbox does not admit an otherwise owner-controlled
39
+ * XDG_RUNTIME_DIR such as /run/user/<uid>. Keep the primary sockets under the
40
+ * node's owner-bound state home, which the runtime already admits, and use a
41
+ * short private tmp path only when the Unix socket length limit requires it.
42
+ * The runtime owns directory creation and permissions; `anet node create`
43
+ * only persists the identity of the two sockets.
44
+ */
45
+ export declare function grokCopresenceSocketPaths(nodeId: string, options?: GrokSocketPathOptions): {
46
+ leaderSocket: string;
47
+ attachSocket: string;
48
+ };
49
+ export type GrokAttachTarget = {
50
+ ok: true;
51
+ socketPath: string;
52
+ } | {
53
+ ok: false;
54
+ reason: "not_grok_build_cli" | "headless" | "missing_attach_socket";
55
+ };
56
+ /**
57
+ * `anet grok attach` eligibility. The CLI is the only human join path;
58
+ * this is the shipped decision so tests can drive it without a TTY.
59
+ */
60
+ export declare function resolveGrokAttachTarget(input: {
61
+ runtime: string;
62
+ grokCopresence?: unknown;
63
+ grokAttachSocket?: unknown;
64
+ }): GrokAttachTarget;
65
+ export declare function grokBuildCliCreationFields(runtime: string, nodeId: string, headless?: boolean, options?: GrokSocketPathOptions): GrokCopresenceProfileFields | Record<string, never>;
@@ -0,0 +1,19 @@
1
+ /** One-line limitation list shown wherever co-presence is offered (CLI help,
2
+ * picker, create warning). Keep it one line — it is appended to menus. */
3
+ export declare const GROK_COPRESENCE_EXPERIMENTAL_NOTE_ZH = "\u5B9E\u9A8C\u6027\uFF1A\u4EBA\u5728 TUI \u8F93\u5165\u6846\u6253\u5B57\u65F6\u7F51\u7EDC\u4EFB\u52A1\u4F1A\u6392\u961F\u76F4\u5230\u8D85\u65F6\uFF1Bgrok \u987B\u9489\u5728\u5DF2\u9A8C\u8BC1\u7248\u672C\uFF08\u65B0\u7248\u4F1A\u62D2\u7EDD\u542F\u52A8\uFF09\uFF1BmacOS \u9700\u7279\u6B8A\u5904\u7406\uFF1B\u4E0D\u52A0\u8F7D .agents/skills \u6280\u80FD\u3002\u8981\u7A33\u5B9A\u63A5\u6D3B\u7528\u9ED8\u8BA4\u7684 ACP\u3002";
4
+ export declare const GROK_COPRESENCE_EXPERIMENTAL_NOTE_EN = "Experimental: network tasks queue until timeout while a human is typing in the TUI; grok must be pinned to a verified build (newer builds refuse to start); macOS needs special handling; .agents/skills skills are not loaded. For a stable node use the default ACP mode.";
5
+ export type GrokCreateModeResult = {
6
+ ok: true;
7
+ runtime: string | undefined;
8
+ copresenceRequested: boolean;
9
+ } | {
10
+ ok: false;
11
+ error: string;
12
+ };
13
+ /**
14
+ * Resolve the runtime string a NEW node is created with.
15
+ *
16
+ * Non-Grok runtimes (and an absent runtime) pass through untouched — this
17
+ * helper only decides between the two Grok lanes.
18
+ */
19
+ export declare function resolveGrokCreateRuntime(rawRuntime: string | undefined, copresence: unknown): GrokCreateModeResult;
@@ -0,0 +1,14 @@
1
+ export interface HostTelemetry {
2
+ hostname: string;
3
+ ip: string | null;
4
+ cpu_load_1min: number | null;
5
+ cpu_cores: number | null;
6
+ mem_total_gb: number | null;
7
+ mem_used_gb: number | null;
8
+ mem_avail_gb: number | null;
9
+ disk_total_gb: number | null;
10
+ disk_used_gb: number | null;
11
+ disk_avail_gb: number | null;
12
+ }
13
+ export declare function getHostTelemetry(): HostTelemetry;
14
+ export declare function _clearHostTelemetryCache(): void;
@@ -0,0 +1,4 @@
1
+ export declare const LOOPBACK_HUB_HEALTH_TIMEOUT_MS = 2000;
2
+ export declare const REMOTE_HUB_HEALTH_TIMEOUT_MS = 10000;
3
+ export declare const HUB_HEALTH_TIMEOUT_ENV = "ANET_HUB_HEALTH_TIMEOUT_MS";
4
+ export declare function hubHealthTimeoutMs(hub: string, env?: NodeJS.ProcessEnv): number;
@@ -0,0 +1,64 @@
1
+ export declare const COMMHUB_SERVER_PKG = "@sleep2agi/commhub-server";
2
+ export declare const AGENT_NETWORK_PKG = "@sleep2agi/agent-network";
3
+ export type HubReleaseChannel = "latest" | "preview";
4
+ export type HubVersionSource = "explicit" | "registry" | "cache" | "pinned-floor";
5
+ export interface DistTags {
6
+ latest?: string | null;
7
+ preview?: string | null;
8
+ }
9
+ export declare function isExactSemver(v: string | null | undefined): boolean;
10
+ /** Semver precedence. Unparseable versions sort lowest. */
11
+ export declare function compareSemver(a: string, b: string): number;
12
+ export declare function resolveHubChannel(input: {
13
+ anetVersion: string;
14
+ flag?: string | null;
15
+ anetDistTags: DistTags | null;
16
+ }): {
17
+ channel: HubReleaseChannel;
18
+ reason: string;
19
+ };
20
+ export interface HubVersionDecision {
21
+ version: string;
22
+ source: HubVersionSource;
23
+ channel: HubReleaseChannel | null;
24
+ /** true when `version` is already present in the local bun install cache. */
25
+ cached: boolean;
26
+ /** One-line, human readable "where it came from". */
27
+ origin: string;
28
+ /** Must be printed prominently (stderr). */
29
+ warnings: string[];
30
+ }
31
+ export declare function decideHubServerVersion(input: {
32
+ explicit?: string | null;
33
+ channelFlag?: string | null;
34
+ anetVersion: string;
35
+ anetDistTags: DistTags | null;
36
+ serverDistTags: DistTags | null;
37
+ floor: string;
38
+ cachedVersions: string[];
39
+ }): HubVersionDecision;
40
+ export type ExecFn = (cmd: string, args: string[]) => string;
41
+ export declare function fetchDistTags(exec: ExecFn, pkg: string): DistTags | null;
42
+ export interface CacheFs {
43
+ existsSync(p: string): boolean;
44
+ readdirSync(p: string): string[];
45
+ readFileSync(p: string): string;
46
+ }
47
+ export declare function bunInstallCacheDir(env?: NodeJS.ProcessEnv, home?: string): string;
48
+ /**
49
+ * Versions of commhub-server present in bun's install cache. Bun uses two
50
+ * layouts (`@sleep2agi/commhub-server@<ver-or-hash>@@@1/` and
51
+ * `@sleep2agi/commhub-server/<ver-or-hash>@@@1/`); prerelease parts are
52
+ * hashed in the directory name, so the version is read from package.json.
53
+ */
54
+ export declare function listCachedServerVersions(cacheDir: string, fs?: CacheFs): string[];
55
+ export declare function resolveHubServerVersion(input: {
56
+ explicit?: string | null;
57
+ channelFlag?: string | null;
58
+ anetVersion: string;
59
+ floor: string;
60
+ exec: ExecFn;
61
+ cacheDir: string;
62
+ fs?: CacheFs;
63
+ }): HubVersionDecision;
64
+ export declare function formatHubVersionBanner(d: HubVersionDecision): string;
@@ -0,0 +1,74 @@
1
+ export type ProbeName = "proc" | "ss" | "lsof" | "netstat";
2
+ /** null = 这条探针在本机跑不了(没有 /proc、没装 ss …);数组 = 跑了,这些 PID 在监听。 */
3
+ export interface SocketProbeResult {
4
+ pids: number[];
5
+ /** 端口确实被监听、但属主 PID 读不到(别的用户的进程)。 */
6
+ unresolved?: number;
7
+ }
8
+ export interface HubPidRecord {
9
+ pid: number;
10
+ port: number;
11
+ launcher_pid?: number;
12
+ started_at?: string;
13
+ }
14
+ export interface HubStopProbes {
15
+ platform: NodeJS.Platform;
16
+ socket: Partial<Record<ProbeName, (port: number) => SocketProbeResult | null>>;
17
+ readPidFile: (port: number) => HubPidRecord | null;
18
+ cmdline: (pid: number) => string | null;
19
+ alive: (pid: number) => boolean;
20
+ }
21
+ export type CandidateVerdict = "commhub" | "not-commhub" | "cmdline-unreadable";
22
+ export interface Candidate {
23
+ pid: number;
24
+ source: ProbeName | "pidfile";
25
+ cmdline: string | null;
26
+ verdict: CandidateVerdict;
27
+ }
28
+ export interface HubListenerResolution {
29
+ port: number;
30
+ /** 每条探针的结果,按尝试顺序。 */
31
+ tried: {
32
+ probe: ProbeName | "pidfile";
33
+ outcome: string;
34
+ }[];
35
+ /** 给出端口归属的那条探针;null = 本机没有一条能跑。 */
36
+ authority: ProbeName | null;
37
+ /** 端口被监听但读不到属主 PID 的个数。 */
38
+ unresolved: number;
39
+ /** 核实过是 commhub-server 的 PID —— 只有这些会被停。 */
40
+ hubPids: Candidate[];
41
+ /** 端口上的其他进程 / cmdline 读不到的进程 —— 拒绝动手。 */
42
+ refused: Candidate[];
43
+ }
44
+ export declare function probeOrder(platform: NodeJS.Platform): ProbeName[];
45
+ /** cmdline 是不是 commhub-server。只做核实,不用来挑选进程。 */
46
+ export declare function isCommhubServerCmdline(cmdline: string | null | undefined): boolean;
47
+ /** /proc/net/tcp 或 tcp6 文本 → 在 port 上 LISTEN(st=0A)的 socket inode。 */
48
+ export declare function parseProcNetTcp(text: string, port: number): string[];
49
+ /** `ss -Hltnp 'sport = :PORT'` → pids;有行却没有 users:(…) 的算 unresolved。 */
50
+ export declare function parseSsOutput(text: string, port: number): SocketProbeResult;
51
+ /** Windows `netstat -ano`:`TCP 127.0.0.1:9200 0.0.0.0:0 LISTENING 1234`。 */
52
+ export declare function parseNetstatWindows(text: string, port: number): SocketProbeResult;
53
+ /** macOS `netstat -anv -p tcp`:按表头找 pid 列;本地地址形如 `127.0.0.1.9200` / `*.9200`。 */
54
+ export declare function parseNetstatDarwin(text: string, port: number): SocketProbeResult;
55
+ export declare function resolveHubListener(port: number, probes: HubStopProbes): HubListenerResolution;
56
+ export interface StopHubDeps {
57
+ probes: HubStopProbes;
58
+ kill: (pid: number, signal: "SIGTERM" | "SIGKILL") => void;
59
+ sleep: (ms: number) => Promise<void>;
60
+ /** /health 是否 ok —— 与探针无关的独立判据。 */
61
+ healthy: () => Promise<boolean>;
62
+ log: (line: string) => void;
63
+ error: (line: string) => void;
64
+ graceMs?: number;
65
+ }
66
+ export interface StopHubResult {
67
+ code: 0 | 1;
68
+ killed: number[];
69
+ refused: Candidate[];
70
+ }
71
+ export declare function stopHub(port: number, d: StopHubDeps): Promise<StopHubResult>;
72
+ export declare function procNetListeners(port: number, procRoot?: string): SocketProbeResult | null;
73
+ export declare function defaultHubStopProbes(readPidFile: (port: number) => HubPidRecord | null, platform?: NodeJS.Platform): HubStopProbes;
74
+ export declare function readCmdline(pid: number, platform?: NodeJS.Platform): string | null;
@@ -0,0 +1,20 @@
1
+ /**
2
+ * 把 hub 的 TEXT 时间戳显示给人看。
3
+ *
4
+ * 🔴 原先是**原样打印**:
5
+ *
6
+ * updated: 2026-08-31 00:20:11
7
+ *
8
+ * 那是 UTC,**没有任何时区标记**。同一时刻本地是 `08:22:41 CST` ——
9
+ * 于是一个 **2 分钟前**刚心跳过的节点,在 UTC+8 的用户眼里像是 **8 小时前**的。
10
+ *
11
+ * 这不是假想:2026-08-31 我自己就这么读错过一次,据此差点报出「舰队心跳陈旧
12
+ * 8.3 小时」。**CLI 在主动制造这个误读。**
13
+ *
14
+ * 所以显示两样东西:
15
+ * - **相对时长**(人真正想知道的那个)
16
+ * - 绝对值,并**显式标 UTC**(便于和日志、issue 里的时间对齐)
17
+ */
18
+ export declare function formatHubTime(raw: unknown, nowMs?: number): string;
19
+ /** 人读的时长。负数(时钟偏差/未来时间)如实说,不折成 0。 */
20
+ export declare function formatAgo(deltaMs: number): string;