@sleep2agi/agent-network 2.3.0-preview.14 → 2.3.0-preview.141

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 (151) 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-home-enforce.d.ts +71 -0
  33. package/dist/src/codex-lifecycle-account.d.ts +104 -0
  34. package/dist/src/codex-lifecycle-canary.d.ts +20 -0
  35. package/dist/src/codex-lifecycle-facts.d.ts +53 -0
  36. package/dist/src/codex-lifecycle-fork.d.ts +91 -0
  37. package/dist/src/codex-lifecycle-preflight.d.ts +77 -0
  38. package/dist/src/codex-lifecycle-receipt.d.ts +53 -0
  39. package/dist/src/codex-lifecycle-restart.d.ts +88 -0
  40. package/dist/src/codex-login-share-guard.d.ts +146 -0
  41. package/dist/src/codex-menu.d.ts +78 -0
  42. package/dist/src/codex-model-default.d.ts +6 -0
  43. package/dist/src/codex-node-login.d.ts +98 -0
  44. package/dist/src/codex-resume.d.ts +89 -0
  45. package/dist/src/codex-tui-client-health.d.ts +30 -0
  46. package/dist/src/commhub-response.d.ts +1 -0
  47. package/dist/src/controlled-upload.d.ts +83 -0
  48. package/dist/src/copresence-deps.d.ts +22 -0
  49. package/dist/src/copresence-identity.d.ts +353 -0
  50. package/dist/src/copresence-startup-diagnosis.d.ts +17 -0
  51. package/dist/src/daemon-anet-bin.d.ts +32 -0
  52. package/dist/src/daemon-capability-display.d.ts +110 -0
  53. package/dist/src/daemon-capability-display.js +21 -0
  54. package/dist/src/daemon-runtime-path-preflight.d.ts +22 -0
  55. package/dist/src/daemon-runtime-staleness.d.ts +13 -0
  56. package/dist/src/dashboard-managed-process.d.ts +35 -0
  57. package/dist/src/display-width.d.ts +27 -0
  58. package/dist/src/doctor-node-count.d.ts +28 -0
  59. package/dist/src/environ-alias.d.ts +14 -0
  60. package/dist/src/grok-attach-client.d.ts +129 -0
  61. package/dist/src/grok-build-drift.d.ts +15 -0
  62. package/dist/src/grok-copresence-disclosure.d.ts +11 -0
  63. package/dist/src/grok-copresence-orchestration.d.ts +75 -0
  64. package/dist/src/grok-copresence-profile.d.ts +65 -0
  65. package/dist/src/grok-create-mode.d.ts +19 -0
  66. package/dist/src/host-telemetry.d.ts +14 -0
  67. package/dist/src/hub-health-timeout.d.ts +4 -0
  68. package/dist/src/hub-server-version.d.ts +64 -0
  69. package/dist/src/hub-stop.d.ts +74 -0
  70. package/dist/src/hub-time-display.d.ts +20 -0
  71. package/dist/src/hub-version-skew.d.ts +19 -0
  72. package/dist/src/im/correlation-store.d.ts +34 -0
  73. package/dist/src/im/feishu/adapter.d.ts +80 -0
  74. package/dist/src/im/feishu/bridge.d.ts +78 -14
  75. package/dist/src/im/feishu/config.d.ts +31 -0
  76. package/dist/src/im/feishu/hub-upload.d.ts +88 -0
  77. package/dist/src/im/feishu/outbound-route.d.ts +62 -0
  78. package/dist/src/im/feishu/worker-lifecycle.d.ts +13 -0
  79. package/dist/src/im/feishu/worker.js +187 -144
  80. package/dist/src/im/types.d.ts +30 -1
  81. package/dist/src/inbox-drain.d.ts +20 -0
  82. package/dist/src/local-process-state.d.ts +12 -0
  83. package/dist/src/locale-diagnostic.d.ts +12 -0
  84. package/dist/src/login-client-label.d.ts +6 -0
  85. package/dist/src/ls-columns.d.ts +15 -0
  86. package/dist/src/mock-llm.d.ts +12 -0
  87. package/dist/src/node-activity-log.d.ts +4 -0
  88. package/dist/src/node-clone.d.ts +134 -0
  89. package/dist/src/node-delete-hub.d.ts +42 -0
  90. package/dist/src/node-files.d.ts +62 -0
  91. package/dist/src/node-locate.d.ts +60 -0
  92. package/dist/src/node-not-found.d.ts +1 -0
  93. package/dist/src/node-running-guard.d.ts +9 -0
  94. package/dist/src/node-server-identity.d.ts +35 -0
  95. package/dist/src/node-server-payload.d.ts +66 -0
  96. package/dist/src/node-server-rules-file.d.ts +14 -0
  97. package/dist/src/node-server-version.d.ts +39 -0
  98. package/dist/src/node-server.js +8 -1
  99. package/dist/src/node-skills.d.ts +32 -0
  100. package/dist/src/normalize-runtime.d.ts +29 -2
  101. package/dist/src/offline-age.d.ts +29 -0
  102. package/dist/src/one-line-cell.d.ts +20 -0
  103. package/dist/src/opencode-agent-node-pair.d.ts +25 -0
  104. package/dist/src/opencode-auth-login.d.ts +43 -0
  105. package/dist/src/opencode-free-tier.d.ts +27 -0
  106. package/dist/src/opencode-generation-create.d.ts +27 -0
  107. package/dist/src/opencode-generation-record.d.ts +24 -0
  108. package/dist/src/opencode-launch-env.d.ts +13 -0
  109. package/dist/src/opencode-owner-mode.d.ts +6 -0
  110. package/dist/src/opencode-package-binary.d.ts +44 -0
  111. package/dist/src/opencode-pin.d.ts +61 -0
  112. package/dist/src/opencode-preset.d.ts +73 -0
  113. package/dist/src/opencode-runtime-binding.d.ts +30 -0
  114. package/dist/src/opencode-safe-root.d.ts +36 -0
  115. package/dist/src/opencode-smoke-env.d.ts +1 -0
  116. package/dist/src/opencode-versions.d.ts +44 -0
  117. package/dist/src/outbound-attachments.d.ts +60 -0
  118. package/dist/src/outbound-tool-names.d.ts +1 -0
  119. package/dist/src/owned-roots.d.ts +58 -0
  120. package/dist/src/owner-env-file.d.ts +2 -0
  121. package/dist/src/package-mode-preflight.d.ts +41 -0
  122. package/dist/src/posix-codex-copresence.d.ts +35 -0
  123. package/dist/src/posix-modes.d.ts +36 -0
  124. package/dist/src/primary-network.d.ts +23 -0
  125. package/dist/src/private-state.d.ts +10 -0
  126. package/dist/src/process-telemetry.d.ts +12 -0
  127. package/dist/src/profile-serialize.d.ts +1 -0
  128. package/dist/src/project-key.d.ts +1 -0
  129. package/dist/src/reply-local-links.d.ts +47 -0
  130. package/dist/src/reply-originator.d.ts +20 -0
  131. package/dist/src/resume-runtime-infer.d.ts +18 -0
  132. package/dist/src/rules-file.d.ts +53 -0
  133. package/dist/src/secret-shell-guidance.d.ts +4 -0
  134. package/dist/src/session-status-class.d.ts +48 -0
  135. package/dist/src/sibling-agent-node.d.ts +23 -0
  136. package/dist/src/stale-socket.d.ts +118 -0
  137. package/dist/src/subcommand-redirect.d.ts +26 -0
  138. package/dist/src/task-trace.d.ts +33 -0
  139. package/dist/src/tmux-attach.d.ts +11 -0
  140. package/dist/src/tmux-capability.d.ts +58 -0
  141. package/dist/src/tmux-exact-target.d.ts +36 -0
  142. package/dist/src/tmux-format.d.ts +20 -0
  143. package/dist/src/tmux-pane-prompt.d.ts +22 -0
  144. package/dist/src/tmux.d.ts +44 -0
  145. package/dist/src/token-cli.d.ts +13 -0
  146. package/dist/src/tool-allowlist.d.ts +28 -0
  147. package/dist/src/unsafe-package-path-reason.d.ts +31 -0
  148. package/dist/src/upgrade-channel.d.ts +31 -0
  149. package/dist/src/win-launcher.d.ts +20 -0
  150. package/dist/src/windows-codex-copresence.d.ts +60 -0
  151. package/package.json +11 -6
@@ -72,13 +72,42 @@ export interface NormalizedIMEvent {
72
72
  mentioned: boolean;
73
73
  content: {
74
74
  text?: string;
75
- /** Local filesystem paths to already-downloaded images. */
75
+ /** Local filesystem paths to already-downloaded images.
76
+ *
77
+ * RFC-020 §17 backward-compat shim: the new richer
78
+ * `attachments[]` field below is the canonical source going
79
+ * forward. `images` stays a `string[]` of paths so an older
80
+ * agent-node worker reading this envelope across a rolling
81
+ * upgrade doesn't crash. New workers prefer `attachments`,
82
+ * old workers ignore it and keep using `images`. */
76
83
  images?: string[];
77
84
  files?: {
78
85
  name: string;
79
86
  path?: string;
80
87
  url?: string;
81
88
  }[];
89
+ /** RFC-020 §17 cross-machine attachment descriptors.
90
+ *
91
+ * Each entry mirrors `meta.attachments[]` on commhub tasks
92
+ * (`{ type, file_id?, path?, mime?, name?, size? }`). The
93
+ * feishu bridge populates `file_id` by uploading inbound
94
+ * files to `/api/upload` so cross-host agents delegated via
95
+ * `commhub_send_task(meta.attachments=...)` can fetch via
96
+ * `/api/files/<id>`. When upload fails, `file_id` is absent
97
+ * and the descriptor degrades to path-only (single-host
98
+ * still works via local Read; no regression vs pre-fix
99
+ * baseline).
100
+ *
101
+ * Always populated alongside `images` for the same files —
102
+ * duplication is intentional for rolling-upgrade safety. */
103
+ attachments?: Array<{
104
+ type: "image" | "file";
105
+ path?: string;
106
+ file_id?: string;
107
+ mime?: string;
108
+ name?: string;
109
+ size?: number;
110
+ }>;
82
111
  };
83
112
  /**
84
113
  * Original platform payload. Default: held in memory only and dropped after
@@ -0,0 +1,20 @@
1
+ export interface InboxPage<T> {
2
+ ok?: boolean;
3
+ messages?: T[];
4
+ }
5
+ export interface DrainOptions<T extends {
6
+ id: string;
7
+ }> {
8
+ fetchPage: (limit: number) => Promise<InboxPage<T> | undefined | null>;
9
+ handle: (msg: T) => Promise<void>;
10
+ pageSize?: number;
11
+ maxPages?: number;
12
+ }
13
+ export interface DrainResult {
14
+ delivered: number;
15
+ pages: number;
16
+ stoppedBy: "empty" | "short-page" | "max-pages" | "no-progress" | "fetch-error";
17
+ }
18
+ export declare function drainInbox<T extends {
19
+ id: string;
20
+ }>(opts: DrainOptions<T>): Promise<DrainResult>;
@@ -0,0 +1,12 @@
1
+ export type LocalProcessState = {
2
+ kind: "alive";
3
+ pid: number;
4
+ } | {
5
+ kind: "stale";
6
+ pid: number;
7
+ } | {
8
+ kind: "none";
9
+ };
10
+ export declare function describeLocalProcess(state: LocalProcessState): string;
11
+ /** doctor 印完节点清单后的那一句:说清这一列量的是本机,不是 hub。 */
12
+ export declare const LOCAL_VS_HUB_NOTE: string;
@@ -0,0 +1,12 @@
1
+ export interface LocaleDiagnostic {
2
+ effectiveVariable: "LC_ALL" | "LC_CTYPE" | "LANG" | null;
3
+ effectiveValue: string | null;
4
+ shouldWarn: boolean;
5
+ }
6
+ /**
7
+ * Resolve the locale with the same precedence used by POSIX libc. Windows
8
+ * does not use these variables as its process Unicode boundary, so prescribing
9
+ * a POSIX locale there would be misleading.
10
+ */
11
+ export declare function diagnoseLocale(env: Readonly<Record<string, string | undefined>>, platform: string): LocaleDiagnostic;
12
+ export declare function formatLocaleSource(diagnostic: LocaleDiagnostic): string;
@@ -0,0 +1,6 @@
1
+ export declare const CLIENT_LABEL_MAX = 64;
2
+ export declare function anetClientLabel(env: {
3
+ version?: string | null;
4
+ host?: string | null;
5
+ command: string;
6
+ }): string;
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 一列该多宽:装得下表头,也装得下这一列里最长的那个值。
3
+ *
4
+ * 🔴 两处用它的地方来源不同,但问题一样:
5
+ * - `anet node ls` 的 RUNTIME 列:值域来自 `SUPPORTED_RUNTIME_NAMES`(唯一真源);
6
+ * - `anet status` / `anet tasks` 的 STATUS 列:值域散在 server/ 里(另一个包),
7
+ * CLI 没法 import —— 但**要打印的那些行就在手上**,直接从数据算。
8
+ *
9
+ * 两种情况都不该写死一个数:写死的那个,下一次加 runtime / 加状态时就漂了。
10
+ */
11
+ export declare function columnWidth(values: readonly unknown[], header: string): number;
12
+ /** RUNTIME 列的专用入口 —— 保留原名,调用点不用改。 */
13
+ export declare function runtimeColumnWidth(names: readonly string[], header?: string): number;
14
+ export declare function lsHeaderRow(runtimeWidth: number): string;
15
+ export declare function lsSeparatorRow(runtimeWidth: number): string;
@@ -0,0 +1,12 @@
1
+ export declare const MOCK_LLM_FALLBACK = "(mock LLM: no rule matched)";
2
+ export type MockLlmRule = Readonly<{
3
+ in_substring: string;
4
+ out: string;
5
+ }>;
6
+ export type MockLlmResolution = Readonly<{
7
+ reply: string;
8
+ matched: boolean;
9
+ ruleIndex: number | null;
10
+ }>;
11
+ export declare function loadMockLlmRules(path: string): readonly MockLlmRule[];
12
+ export declare function resolveMockLlmReply(rules: readonly MockLlmRule[], prompt: string, warn?: (message: string) => void): MockLlmResolution;
@@ -0,0 +1,4 @@
1
+ export interface ActivityLogSink {
2
+ append(line: string): void;
3
+ }
4
+ export declare function createActivityLogSink(baseDir: string, alias: string, now?: () => Date): ActivityLogSink;
@@ -0,0 +1,134 @@
1
+ export interface CloneArgs {
2
+ source: string;
3
+ target: string;
4
+ /** Raw --workdir as typed (resolved later against cwd). */
5
+ workdir?: string;
6
+ model?: string;
7
+ start: boolean;
8
+ }
9
+ export type CloneArgsResult = {
10
+ ok: true;
11
+ args: CloneArgs;
12
+ } | {
13
+ ok: false;
14
+ error: string;
15
+ } | {
16
+ ok: false;
17
+ help: true;
18
+ };
19
+ export declare const NODE_CLONE_USAGE = "anet node clone <source> <new-name> [--workdir <dir>] [--model <id>] [--start]\nanet node create <new-name> --from <source> [--workdir <dir>] [--model <id>] [--start]\n\n Make a new node with the same settings as <source>, under a NEW identity.\n The clone is registered with the Hub as its own node (new node_id + token);\n it never shares the source's identity, session, login or logs.\n\n Copied: runtime, model, tools, permission flags, prompts, non-secret env,\n rules file / skills / .mcp.json (with --workdir)\n Regenerated: node_id, token, session id, co-presence sockets\n Not copied: token, sessions/threads, logs, inbox, channel bot credentials,\n codex auth.json, secret env values (key names are kept)\n\n --workdir <dir> Put the clone in another project directory (created if\n missing; path must be ASCII). Default: the source's project\n directory (the current one), sharing its rules file/skills.\n --model <id> Use a different model than the source.\n --start Start the clone right after creating it.\n\n Never copy a node directory with cp -r: the copy keeps the same node_id and\n token, so the Hub delivers every task to both processes and it runs twice.";
20
+ /**
21
+ * Parse the tokens after the verb.
22
+ * mode "clone": [<source>, <new>, ...flags]
23
+ * mode "create-from": [<new>, ...flags] with a required --from <source>
24
+ */
25
+ export declare function parseCloneArgs(tokens: readonly string[], mode: "clone" | "create-from"): CloneArgsResult;
26
+ /** Project rule: node working directories are ASCII (aliases may be Chinese, directories not). */
27
+ export declare function isAsciiPath(p: string): boolean;
28
+ export interface RefusalInput {
29
+ sourceId: string;
30
+ sourceProfile: Record<string, any>;
31
+ target: string;
32
+ sourceNodeDir: string;
33
+ targetNodeDir: string;
34
+ /** Present only when --workdir was given; absolute. */
35
+ explicitWorkdir?: string;
36
+ }
37
+ /** Every reason to stop before touching the Hub or the disk. null = go. */
38
+ export declare function cloneRefusal(i: RefusalInput): string | null;
39
+ export interface LedgerItem {
40
+ item: string;
41
+ note?: string;
42
+ }
43
+ export interface CloneLedger {
44
+ copied: LedgerItem[];
45
+ regenerated: LedgerItem[];
46
+ skipped: LedgerItem[];
47
+ /** env keys whose value is a secret: the clone references `ref`, which the user must set. */
48
+ secrets: {
49
+ key: string;
50
+ ref: string;
51
+ }[];
52
+ }
53
+ export declare function emptyLedger(): CloneLedger;
54
+ export interface PlanInput {
55
+ sourceProfile: Record<string, any>;
56
+ target: string;
57
+ newNodeId: string;
58
+ /** Absolute project directory the clone will live in. */
59
+ targetWorkdir: string;
60
+ modelOverride?: string;
61
+ /** New claude-code-cli session id. */
62
+ newSession: () => string;
63
+ /** grok co-presence socket fields for the new node id (grokBuildCliCreationFields). */
64
+ grokFields?: (nodeId: string) => Record<string, unknown>;
65
+ }
66
+ /** Build the clone's profile (no token yet) and the ledger of what happened to each field. */
67
+ export declare function planCloneProfile(p: PlanInput, ledger?: CloneLedger): {
68
+ profile: Record<string, any>;
69
+ ledger: CloneLedger;
70
+ };
71
+ /** Files a codex-home may carry to the clone. Never auth.json, never .anet-copresence.env. */
72
+ export declare const CODEX_HOME_COPY: readonly ["config.toml", "AGENTS.md", "version.json"];
73
+ export declare const CODEX_HOME_COPY_DIRS: readonly ["skills"];
74
+ /** Workdir-level settings copied only when the clone gets its own --workdir. */
75
+ export declare const WORKDIR_COPY_FILES: readonly ["CLAUDE.md", "AGENTS.md"];
76
+ export declare const WORKDIR_COPY_DIRS: readonly [".claude/skills", ".agents/skills", ".grok/skills", ".opencode/skill", ".opencode/skills"];
77
+ /** Recursive copy that never follows symlinks and never copies credential-looking files. Returns files copied. */
78
+ export declare function copyTreeSafe(from: string, to: string, skipped: LedgerItem[], label: string): number;
79
+ /** Strip values from env/headers of every MCP server; drop the commhub entry (regenerated at start). */
80
+ export declare function sanitizeMcpJson(raw: string): {
81
+ text: string;
82
+ blanked: string[];
83
+ };
84
+ export interface CopyFilesInput {
85
+ sourceNodeDir: string;
86
+ targetNodeDir: string;
87
+ sourceWorkdir: string;
88
+ targetWorkdir: string;
89
+ }
90
+ /** Copy the whitelisted on-disk settings. The target node dir must already exist. */
91
+ export declare function copyCloneFiles(i: CopyFilesInput, ledger: CloneLedger): void;
92
+ export interface RunCloneInput {
93
+ sourceId: string;
94
+ /** Raw source config.json (as stored, before normalisation). */
95
+ sourceProfile: Record<string, any>;
96
+ target: string;
97
+ sourceNodeDir: string;
98
+ sourceWorkdir: string;
99
+ targetWorkdir: string;
100
+ /** True when the user passed --workdir. */
101
+ explicitWorkdir: boolean;
102
+ modelOverride?: string;
103
+ newNodeId: () => string;
104
+ newSession: () => string;
105
+ grokFields?: (nodeId: string) => Record<string, unknown>;
106
+ /** Hub registration — returns the new node's ntok_. Same endpoint `anet node create` uses. */
107
+ register: (profile: Record<string, any>) => Promise<string>;
108
+ /** Write config.json into targetNodeDir (the CLI passes its create writer). */
109
+ persist: (profile: Record<string, any>, targetNodeDir: string) => void;
110
+ }
111
+ export type RunCloneResult = {
112
+ ok: true;
113
+ profile: Record<string, any>;
114
+ ledger: CloneLedger;
115
+ targetNodeDir: string;
116
+ } | {
117
+ ok: false;
118
+ stage: "refused" | "register" | "write";
119
+ error: string;
120
+ };
121
+ export declare function runNodeClone(i: RunCloneInput): Promise<RunCloneResult>;
122
+ /** Test/default writer: the same config.json whitelist `anet node create` persists, mode 0600. */
123
+ export declare function defaultClonePersist(profile: Record<string, any>, targetNodeDir: string): void;
124
+ /** The summary table printed after a clone. Never prints a token or a secret value. */
125
+ export declare function formatCloneSummary(r: {
126
+ source: string;
127
+ target: string;
128
+ profile: Record<string, any>;
129
+ ledger: CloneLedger;
130
+ targetNodeDir: string;
131
+ sourceNodeId?: string;
132
+ }): string;
133
+ /** realpath that tolerates a missing path (resolves the nearest existing parent). */
134
+ export declare function realpathLoose(p: string): string;
@@ -0,0 +1,42 @@
1
+ export type HubRemoval =
2
+ /** The Hub had a row with exactly this node_id and deleted it. */
3
+ {
4
+ kind: "removed";
5
+ nodeId: string;
6
+ }
7
+ /** No row with this node_id. `otherRows` share the alias but belong to other nodes — untouched. */
8
+ | {
9
+ kind: "absent";
10
+ nodeId: string;
11
+ otherRows: string[];
12
+ }
13
+ /** Nothing to do on a Hub: no Hub configured, or a legacy config without node_id. */
14
+ | {
15
+ kind: "skipped";
16
+ reason: "no-hub" | "no-node-id";
17
+ }
18
+ /** Unreachable / HTTP error / not logged in. Local deletion still happens; caller exits non-zero. */
19
+ | {
20
+ kind: "failed";
21
+ nodeId: string;
22
+ reason: string;
23
+ };
24
+ export type HubRemovalInput = {
25
+ hub?: string;
26
+ token?: string;
27
+ nodeId?: string;
28
+ alias?: string;
29
+ fetchImpl?: typeof fetch;
30
+ timeoutMs?: number;
31
+ };
32
+ export declare function removeNodeFromHub(input: HubRemovalInput): Promise<HubRemoval>;
33
+ /** The exact command that retries only the Hub half once the local files are gone. */
34
+ export declare function hubRetryCommand(nodeId: string, hub?: string): string;
35
+ /** Lines to print for a removal result. `warn` lines go to stderr. */
36
+ export declare function describeHubRemoval(r: HubRemoval, ctx: {
37
+ displayName: string;
38
+ hub?: string;
39
+ }): {
40
+ info: string[];
41
+ warn: string[];
42
+ };
@@ -0,0 +1,62 @@
1
+ export declare const NODE_FILE_READ_MAX_BYTES: number;
2
+ export declare const NODE_FILES_LIST_MAX = 1000;
3
+ export declare const NODE_FILE_PATH_MAX = 1024;
4
+ /** 回给 hub 的 JSON 最长这么多字符(hub 端 ack 上限相同)。 */
5
+ export declare const NODE_FILES_RESULT_MAX_CHARS: number;
6
+ export type NodeFileType = "dir" | "file" | "symlink" | "other";
7
+ export type HiddenReason = "secret" | "skipped";
8
+ export interface NodeFileEntry {
9
+ name: string;
10
+ type: NodeFileType;
11
+ /** 普通文件的字节数;凭据文件不给。 */
12
+ size?: number;
13
+ /** 毫秒时间戳。 */
14
+ mtime?: number;
15
+ hidden_reason?: HiddenReason;
16
+ /** 目录(或指向目录的软链接)不允许进入。 */
17
+ no_descend?: boolean;
18
+ /** 软链接:指向工作目录内的什么;指向外面或断链为 null(不透露目标)。 */
19
+ link_type?: "dir" | "file" | null;
20
+ }
21
+ export interface NodeFilesListResult {
22
+ path: string;
23
+ entries: NodeFileEntry[];
24
+ truncated: boolean;
25
+ total: number;
26
+ }
27
+ export type NodeFileReadKind = "text" | "binary" | "too_large" | "secret";
28
+ export interface NodeFileReadResult {
29
+ path: string;
30
+ name: string;
31
+ kind: NodeFileReadKind;
32
+ size?: number;
33
+ mtime?: number;
34
+ content?: string;
35
+ hidden_reason?: HiddenReason;
36
+ }
37
+ /**
38
+ * 纯函数:一个路径是否属于凭据。
39
+ * relPosix —— 相对工作目录(请求的路径,或 realpath 之后相对工作目录的路径)。
40
+ * rootAbs —— 工作目录自身的绝对路径(posix);只作为「祖先目录」参与判定:工作目录本身
41
+ * 就在 .claude/ .codex/ 之类里面时,里面的一切都算凭据;在 .anet/ 里面时
42
+ * config.json* 算凭据。工作目录自己的名字不参与文件名规则。
43
+ * 任一祖先段(含末段)是凭据目录 → secret;末段按文件名规则判。大小写不敏感(macOS 默认不分大小写)。
44
+ */
45
+ export declare function secretReasonFor(relPosix: string, rootAbs?: string): "secret" | null;
46
+ /** 纯函数:这个目录能不能进入。凭据目录 → secret;node_modules → skipped;路径上任一段命中同样不行。 */
47
+ export declare function noDescendReasonFor(relPosix: string, rootAbs?: string): HiddenReason | null;
48
+ /** 客户端给的路径 → 规范化相对路径("" = 根)。不合法抛错,错误信息不回显输入。 */
49
+ export declare function normalizeNodeRelPath(raw: unknown): string;
50
+ export interface ResolvedNodePath {
51
+ rootReal: string;
52
+ real: string;
53
+ /** realpath 之后相对根的路径(posix)。 */
54
+ relReal: string;
55
+ }
56
+ /**
57
+ * 解析并收在工作目录里:realpath(根) + realpath(根/rel),后者必须在前者之内。
58
+ * 不存在抛 `not found`;逃出去抛 `outside the work dir`。
59
+ */
60
+ export declare function resolveInsideWorkDir(workDir: string, rel: string): Promise<ResolvedNodePath>;
61
+ export declare function listNodeFiles(workDir: string, rawPath: unknown): Promise<NodeFilesListResult>;
62
+ export declare function readNodeFile(workDir: string, rawPath: unknown): Promise<NodeFileReadResult>;
@@ -0,0 +1,60 @@
1
+ export declare const CHILD_WORKDIRS_FILE = "child-workdirs.json";
2
+ export declare function childWorkdirsPath(root: string): string;
3
+ /** Same reader as agent-node's readChildWorkdirs: only absolute string values count. */
4
+ export declare function readChildWorkdirs(root: string): Record<string, string>;
5
+ /**
6
+ * Record that `alias`, created from `root`, lives in `workdir`.
7
+ * Not recorded when `workdir` is `root` itself, or when `aliasTakenHere` — the
8
+ * host daemon resolves a registered alias to the registered workdir, so an
9
+ * entry for a name that also exists in `root` would hide the local node from it.
10
+ */
11
+ export declare function recordChildWorkdir(root: string, alias: string, workdir: string, aliasTakenHere: boolean): boolean;
12
+ /** `<root>/.anet/nodes/<id>` → `<root>`; anything else → null. */
13
+ export declare function rootOfNodeDir(nodeDir: string): string | null;
14
+ /** `node_dir` of every record in the codex login index directory. */
15
+ export declare function codexIndexNodeDirs(indexDir: string): string[];
16
+ /** Every other .anet root the indexes point at, canonical, deduplicated, existing, excluding `cwdRoot`. */
17
+ export declare function otherNodeRoots(cwdRoot: string, codexIndexDir: string): string[];
18
+ export interface NodeMatch {
19
+ /** Canonical .anet root (the directory to `cd` into). */
20
+ root: string;
21
+ /** Directory name under .anet/nodes/. */
22
+ id: string;
23
+ nodeId?: string;
24
+ /** How the ref matched: the directory name, the node_id, or a name/alias field. */
25
+ how: "dir" | "node_id" | "name";
26
+ }
27
+ export interface ProfileLike {
28
+ node_id?: string;
29
+ node_name?: string;
30
+ name?: string;
31
+ alias?: string;
32
+ }
33
+ /** All nodes in one root that `ref` names, one entry per node with its strongest match. */
34
+ export declare function matchNodesInRoot(root: string, ref: string, profiles: Array<{
35
+ id: string;
36
+ profile: ProfileLike | null;
37
+ }>): NodeMatch[];
38
+ export type DeleteTarget = {
39
+ kind: "here";
40
+ match: NodeMatch;
41
+ } | {
42
+ kind: "elsewhere";
43
+ match: NodeMatch;
44
+ } | {
45
+ kind: "ambiguous";
46
+ matches: NodeMatch[];
47
+ } | {
48
+ kind: "none";
49
+ };
50
+ /**
51
+ * Which node `anet node delete <ref>` means.
52
+ * - a directory named `ref` in the current root wins outright (the long-standing
53
+ * behaviour: the node you are standing next to);
54
+ * - otherwise an exact node_id match, if exactly one node has it;
55
+ * - otherwise every match across all roots: one ⇒ that node, several ⇒ ambiguous.
56
+ */
57
+ export declare function decideDeleteTarget(cwdRoot: string, matches: NodeMatch[]): DeleteTarget;
58
+ export declare function deleteCommandFor(m: NodeMatch, force: boolean, quote: (s: string) => string): string;
59
+ export declare function formatDeleteElsewhere(ref: string, m: NodeMatch, force: boolean, quote: (s: string) => string): string[];
60
+ export declare function formatDeleteAmbiguous(ref: string, matches: NodeMatch[], quote: (s: string) => string): string[];
@@ -0,0 +1 @@
1
+ export declare function nodeNotFoundMessage(ref: string, knownNames: string[], suggestion: string | null): string;
@@ -0,0 +1,9 @@
1
+ export declare const isAgentNodeCommand: (cmdline: string) => boolean;
2
+ export interface RunningNodeProbe {
3
+ pidFileContent: string | null;
4
+ isAlive: (pid: number) => boolean;
5
+ commandOf: (pid: number) => string | null;
6
+ }
7
+ /** 返回还活着且确实是 agent-node 的 pid;否则 null(不存在 / 死了 / pid 被别的进程复用)。 */
8
+ export declare const runningNodePid: (probe: RunningNodeProbe) => number | null;
9
+ export declare const alreadyRunningMessage: (displayName: string, pid: number) => string[];
@@ -0,0 +1,35 @@
1
+ export interface NodeIdentityFromConfig {
2
+ node_id?: string;
3
+ node_name?: string;
4
+ model?: string;
5
+ }
6
+ export declare function nodeIdentityFromConfig(path: string | undefined): NodeIdentityFromConfig;
7
+ export interface NodeRowLike {
8
+ node_id?: string | null;
9
+ alias?: string | null;
10
+ runtime?: string | null;
11
+ config_path?: string | null;
12
+ }
13
+ export type NodeIdClaimVerdict = {
14
+ claim: true;
15
+ } | {
16
+ claim: false;
17
+ owner: string;
18
+ runtime: string | null;
19
+ config_path: string | null;
20
+ };
21
+ export declare function nodeIdClaimVerdict(nodeId: string, rows: readonly NodeRowLike[], alias: string): NodeIdClaimVerdict;
22
+ export type NodeIdClaimState = "ok" | "conflict" | "unknown";
23
+ /** 取 hub 上这个 node_id 的行并下结论;任何失败都是 "unknown"(调用方这次不报 node_id)。 */
24
+ export declare function checkNodeIdClaim(opts: {
25
+ hubUrl: string;
26
+ token: string;
27
+ nodeId: string;
28
+ alias: string;
29
+ fetchImpl?: typeof fetch;
30
+ timeoutMs?: number;
31
+ }): Promise<{
32
+ state: NodeIdClaimState;
33
+ verdict?: NodeIdClaimVerdict;
34
+ error?: string;
35
+ }>;
@@ -0,0 +1,66 @@
1
+ /**
2
+ * What gets written to `<project>/.anet/node-server.js` (issue #1216).
3
+ *
4
+ * The target name is not negotiable: `agent-node`'s grok co-presence spawn
5
+ * gate pins the CommHub MCP payload to exactly that path, so whatever the
6
+ * source is, the file that lands there is called `.js`.
7
+ *
8
+ * 🔴 The bug this module exists to remove: the old code copied the source
9
+ * verbatim and justified it with a comment claiming
10
+ *
11
+ * "bun runs .ts content under a .js extension fine"
12
+ *
13
+ * which is false — bun selects its parser from the extension:
14
+ *
15
+ * $ printf 'function f(x: string): void {}\nf("hi");\n' > probe.ts
16
+ * $ cp probe.ts probe.js
17
+ * $ bun probe.ts → runs
18
+ * $ bun probe.js → error: Expected ")" but found ":"
19
+ *
20
+ * An installed npm package never hit it, because its first resolver candidate
21
+ * (`dist/src/node-server.js`) is compiled. Only a source checkout fell through
22
+ * to `src/node-server.ts` — i.e. every local run and every hand-verified PR.
23
+ *
24
+ * And the symptom was three layers from the cause: the node died on
25
+ * `grok copresence CommHub MCP readiness preflight failed (1)`, which names
26
+ * neither a file nor a parse error.
27
+ */
28
+ /** Injected so the decision is testable without spawning anything. */
29
+ export interface TypeScriptBundler {
30
+ /** Returns the self-contained JavaScript for `entryPath`, or throws. */
31
+ bundleSync(entryPath: string): string;
32
+ }
33
+ export declare class NodeServerPayloadError extends Error {
34
+ constructor(message: string);
35
+ }
36
+ /**
37
+ * Decide what bytes belong at the `.js` target for a given source path.
38
+ *
39
+ * A `.js` source is passed through untouched — the published package ships a
40
+ * compiled bundle there, and re-processing it risks changing bytes for no gain.
41
+ *
42
+ * 🔴 A `.ts` source must be **bundled, not merely transpiled**. Stripping types
43
+ * fixes the parse error but leaves the file's relative imports pointing at
44
+ * siblings that do not exist beside the destination:
45
+ *
46
+ * import { inboundChannelMeta } from "./channel-meta.js";
47
+ * → Cannot find module './channel-meta.js' from '<project>/.anet/node-server.js'
48
+ *
49
+ * That second failure is why transpiling alone still ended at
50
+ * "CommHub MCP readiness preflight failed (1)". The published
51
+ * `dist/src/node-server.js` works precisely because it is a self-contained
52
+ * bundle, so a source checkout has to produce the same shape.
53
+ */
54
+ export declare function nodeServerPayloadFor(source: string, sourcePath: string, bundler: TypeScriptBundler | null): string;
55
+ /**
56
+ * The bundler available on this runtime, or null.
57
+ *
58
+ * bun can bundle; the published CLI runs under node and cannot — but it also
59
+ * never resolves a `.ts` candidate (its `dist/` copy wins), so null there is
60
+ * correct rather than a gap.
61
+ *
62
+ * `spawnSync` rather than `Bun.build()` because both call sites are
63
+ * synchronous, and making them async would change the ordering of the file
64
+ * writes around them.
65
+ */
66
+ export declare function ambientTypeScriptTranspiler(): TypeScriptBundler | null;
@@ -0,0 +1,14 @@
1
+ export declare const CLAUDE_CODE_RULES_RUNTIME = "claude";
2
+ export interface RulesDoorbellDeps {
3
+ callCommHub: (method: string, params: Record<string, unknown>) => Promise<any>;
4
+ workDir: string;
5
+ log: (msg: string) => void;
6
+ /** 技能的用户级根目录(~/.claude/skills)取自这里;缺省 os.homedir()。测试注入临时目录。 */
7
+ home?: string;
8
+ }
9
+ /** SSE 事件分派:是 rules_file 门铃就处理并返回 true;其它事件原样返回 false。 */
10
+ export declare function handleRulesFileEvent(event: {
11
+ type?: unknown;
12
+ } | null | undefined, deps: RulesDoorbellDeps): Promise<boolean>;
13
+ /** 连上 / 重连后补拉一次:断线期间桌面端可能已发起请求(hub 侧 60s 内仍 pending)。 */
14
+ export declare function drainRulesFileRequests(deps: RulesDoorbellDeps, why: string): Promise<number>;
@@ -0,0 +1,39 @@
1
+ export declare const NODE_SERVER_VERSION_MARKER_PREFIX = "// anet-node-server-version: ";
2
+ /** The version carried by a node-server payload, or null if it has no valid marker. */
3
+ export declare function readNodeServerVersion(text: string | null | undefined): string | null;
4
+ /**
5
+ * Add the marker if the payload has none. A leading `#!` line stays first so
6
+ * the file is still directly executable.
7
+ */
8
+ export declare function stampNodeServerVersion(payload: string, version: string): string;
9
+ /**
10
+ * Version of the agent-network package that owns `sourcePath`, found by walking
11
+ * up (dist/src/node-server.js → package root is two levels up; src/node-server.ts
12
+ * one level). Null when no agent-network package.json is found.
13
+ */
14
+ export declare function owningAgentNetworkVersion(sourcePath: string): string | null;
15
+ /** Ensure the payload carries a marker, deriving the version from its source package when needed. */
16
+ export declare function ensureNodeServerVersionMarker(payload: string, sourcePath: string): string;
17
+ export type NodeServerWriteDecision = {
18
+ action: "write";
19
+ existingVersion: string | null;
20
+ incomingVersion: string | null;
21
+ } | {
22
+ action: "keep-newer";
23
+ existingVersion: string;
24
+ incomingVersion: string;
25
+ };
26
+ /**
27
+ * Keep the existing file only when BOTH sides carry a valid marker and the
28
+ * existing one is strictly newer. Everything else behaves as before (#549).
29
+ */
30
+ export declare function decideNodeServerWrite(existing: string | null, incoming: string): NodeServerWriteDecision;
31
+ /** The one-line warning printed when a newer file is kept. */
32
+ export declare function nodeServerKeptNewerWarning(existingVersion: string, incomingVersion: string): string;
33
+ export type NodeServerApplyResult = "wrote" | "unchanged" | "kept-newer";
34
+ /**
35
+ * The single write path both cli.ts writers use: stamp the payload, refuse to
36
+ * downgrade a newer existing file (warning once via `warn`), otherwise write
37
+ * when the bytes differ.
38
+ */
39
+ export declare function applyNodeServerPayload(targetPath: string, payload: string, sourcePath: string, warn?: (line: string) => void): NodeServerApplyResult;