@sleep2agi/agent-network 2.3.0-preview.11 → 2.3.0-preview.111

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 (118) 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-meta.d.ts +10 -0
  11. package/dist/src/channel-task-trace.d.ts +14 -0
  12. package/dist/src/claude-vendor-env.d.ts +28 -0
  13. package/dist/src/cli-args.d.ts +8 -0
  14. package/dist/src/cli-version-display.d.ts +16 -0
  15. package/dist/src/client-task-trace.d.ts +9 -0
  16. package/dist/src/client.js +1 -1
  17. package/dist/src/codex-auth-fingerprint.d.ts +211 -0
  18. package/dist/src/codex-copresence-preflight.d.ts +65 -0
  19. package/dist/src/codex-copresence-profile.d.ts +125 -0
  20. package/dist/src/codex-copresence-recovery.d.ts +43 -0
  21. package/dist/src/codex-copresence-thread.d.ts +13 -0
  22. package/dist/src/codex-lifecycle-account.d.ts +104 -0
  23. package/dist/src/codex-lifecycle-canary.d.ts +20 -0
  24. package/dist/src/codex-lifecycle-facts.d.ts +53 -0
  25. package/dist/src/codex-lifecycle-fork.d.ts +91 -0
  26. package/dist/src/codex-lifecycle-preflight.d.ts +77 -0
  27. package/dist/src/codex-lifecycle-receipt.d.ts +44 -0
  28. package/dist/src/codex-lifecycle-restart.d.ts +86 -0
  29. package/dist/src/codex-model-default.d.ts +6 -0
  30. package/dist/src/codex-tui-client-health.d.ts +17 -0
  31. package/dist/src/commhub-response.d.ts +1 -0
  32. package/dist/src/controlled-upload.d.ts +83 -0
  33. package/dist/src/copresence-deps.d.ts +22 -0
  34. package/dist/src/copresence-identity.d.ts +353 -0
  35. package/dist/src/copresence-startup-diagnosis.d.ts +17 -0
  36. package/dist/src/daemon-anet-bin.d.ts +32 -0
  37. package/dist/src/daemon-capability-display.d.ts +110 -0
  38. package/dist/src/daemon-capability-display.js +21 -0
  39. package/dist/src/daemon-runtime-path-preflight.d.ts +22 -0
  40. package/dist/src/daemon-runtime-staleness.d.ts +13 -0
  41. package/dist/src/dashboard-managed-process.d.ts +35 -0
  42. package/dist/src/display-width.d.ts +27 -0
  43. package/dist/src/doctor-node-count.d.ts +28 -0
  44. package/dist/src/environ-alias.d.ts +14 -0
  45. package/dist/src/grok-attach-client.d.ts +129 -0
  46. package/dist/src/grok-build-drift.d.ts +15 -0
  47. package/dist/src/grok-copresence-disclosure.d.ts +11 -0
  48. package/dist/src/grok-copresence-orchestration.d.ts +75 -0
  49. package/dist/src/grok-copresence-profile.d.ts +65 -0
  50. package/dist/src/host-telemetry.d.ts +14 -0
  51. package/dist/src/hub-health-timeout.d.ts +4 -0
  52. package/dist/src/hub-time-display.d.ts +20 -0
  53. package/dist/src/hub-version-skew.d.ts +19 -0
  54. package/dist/src/im/correlation-store.d.ts +34 -0
  55. package/dist/src/im/feishu/adapter.d.ts +80 -0
  56. package/dist/src/im/feishu/bridge.d.ts +78 -14
  57. package/dist/src/im/feishu/config.d.ts +31 -0
  58. package/dist/src/im/feishu/hub-upload.d.ts +88 -0
  59. package/dist/src/im/feishu/outbound-route.d.ts +62 -0
  60. package/dist/src/im/feishu/worker-lifecycle.d.ts +13 -0
  61. package/dist/src/im/feishu/worker.js +187 -144
  62. package/dist/src/im/types.d.ts +30 -1
  63. package/dist/src/inbox-drain.d.ts +20 -0
  64. package/dist/src/local-process-state.d.ts +12 -0
  65. package/dist/src/locale-diagnostic.d.ts +12 -0
  66. package/dist/src/ls-columns.d.ts +15 -0
  67. package/dist/src/mock-llm.d.ts +12 -0
  68. package/dist/src/node-activity-log.d.ts +4 -0
  69. package/dist/src/node-not-found.d.ts +1 -0
  70. package/dist/src/node-running-guard.d.ts +9 -0
  71. package/dist/src/node-server-payload.d.ts +66 -0
  72. package/dist/src/node-server-rules-file.d.ts +12 -0
  73. package/dist/src/node-server.js +7 -1
  74. package/dist/src/normalize-runtime.d.ts +29 -2
  75. package/dist/src/offline-age.d.ts +29 -0
  76. package/dist/src/one-line-cell.d.ts +20 -0
  77. package/dist/src/opencode-agent-node-pair.d.ts +25 -0
  78. package/dist/src/opencode-auth-login.d.ts +43 -0
  79. package/dist/src/opencode-launch-env.d.ts +13 -0
  80. package/dist/src/opencode-owner-mode.d.ts +6 -0
  81. package/dist/src/opencode-package-binary.d.ts +26 -0
  82. package/dist/src/opencode-pin.d.ts +44 -0
  83. package/dist/src/opencode-preset.d.ts +73 -0
  84. package/dist/src/opencode-runtime-binding.d.ts +30 -0
  85. package/dist/src/opencode-safe-root.d.ts +36 -0
  86. package/dist/src/opencode-smoke-env.d.ts +1 -0
  87. package/dist/src/outbound-attachments.d.ts +60 -0
  88. package/dist/src/outbound-tool-names.d.ts +1 -0
  89. package/dist/src/owned-roots.d.ts +58 -0
  90. package/dist/src/owner-env-file.d.ts +2 -0
  91. package/dist/src/package-mode-preflight.d.ts +41 -0
  92. package/dist/src/posix-codex-copresence.d.ts +8 -0
  93. package/dist/src/posix-modes.d.ts +36 -0
  94. package/dist/src/primary-network.d.ts +23 -0
  95. package/dist/src/private-state.d.ts +10 -0
  96. package/dist/src/process-telemetry.d.ts +12 -0
  97. package/dist/src/profile-serialize.d.ts +1 -0
  98. package/dist/src/project-key.d.ts +1 -0
  99. package/dist/src/reply-local-links.d.ts +47 -0
  100. package/dist/src/reply-originator.d.ts +20 -0
  101. package/dist/src/resume-runtime-infer.d.ts +18 -0
  102. package/dist/src/rules-file.d.ts +40 -0
  103. package/dist/src/secret-shell-guidance.d.ts +3 -0
  104. package/dist/src/session-status-class.d.ts +48 -0
  105. package/dist/src/sibling-agent-node.d.ts +23 -0
  106. package/dist/src/stale-socket.d.ts +118 -0
  107. package/dist/src/subcommand-redirect.d.ts +26 -0
  108. package/dist/src/task-trace.d.ts +33 -0
  109. package/dist/src/tmux-attach.d.ts +8 -0
  110. package/dist/src/tmux-capability.d.ts +58 -0
  111. package/dist/src/tmux-exact-target.d.ts +34 -0
  112. package/dist/src/tmux-pane-prompt.d.ts +22 -0
  113. package/dist/src/token-cli.d.ts +13 -0
  114. package/dist/src/tool-allowlist.d.ts +28 -0
  115. package/dist/src/unsafe-package-path-reason.d.ts +17 -0
  116. package/dist/src/win-launcher.d.ts +20 -0
  117. package/dist/src/windows-codex-copresence.d.ts +60 -0
  118. package/package.json +10 -5
@@ -0,0 +1,31 @@
1
+ export interface WakeLogEntryShape {
2
+ ts?: string;
3
+ status?: string;
4
+ summary?: string;
5
+ task_id?: string;
6
+ }
7
+ export interface WakeLogGoalShape {
8
+ goal_id: string;
9
+ progress_log?: WakeLogEntryShape[];
10
+ }
11
+ export interface WakeLogRenderOpts {
12
+ /** Trim to the last N entries. undefined = all. */
13
+ tail?: number;
14
+ }
15
+ /**
16
+ * Format progress_log as a JSON object suitable for `--json` output.
17
+ * Pure. Never reads/writes filesystem. Legacy goals without
18
+ * progress_log render as empty array (not error).
19
+ */
20
+ export declare function renderWakeLogJson(goal: WakeLogGoalShape, opts?: WakeLogRenderOpts): {
21
+ goal_id: string;
22
+ total: number;
23
+ returned: number;
24
+ entries: WakeLogEntryShape[];
25
+ };
26
+ /**
27
+ * Format progress_log as a table for human console output.
28
+ * Column layout mirrors printGoalShow so the two commands read
29
+ * consistently. Empty log renders a single "(none)" line, not an error.
30
+ */
31
+ export declare function renderWakeLogText(goal: WakeLogGoalShape, opts?: WakeLogRenderOpts): string;
@@ -0,0 +1,28 @@
1
+ export interface ActiveNetworkTask {
2
+ taskId: string;
3
+ from: string;
4
+ startedAt: number;
5
+ }
6
+ /** 运行时崩溃没来得及删标记时的兜底:超过这个年龄的标记当不存在。 */
7
+ export declare const ACTIVE_NETWORK_TASK_MAX_AGE_MS: number;
8
+ export declare function parseActiveNetworkTask(raw: string | null | undefined, now: number, maxAgeMs?: number): ActiveNetworkTask | null;
9
+ export type OutboundTool = "commhub_send_task" | "commhub_send_message";
10
+ export type OutboundRewrite = {
11
+ kind: "pass";
12
+ } | {
13
+ kind: "progress_of_active_task";
14
+ taskId: string;
15
+ from: string;
16
+ text: string;
17
+ };
18
+ /**
19
+ * 只在「目标 alias 恰好是当前网络任务的发起方」时改写;发给别人的照常放行——
20
+ * 模型替任务派活给第三方是合法的协作,不能一刀切。
21
+ */
22
+ export declare function decideOutboundRewrite(tool: OutboundTool, args: {
23
+ alias?: unknown;
24
+ task?: unknown;
25
+ message?: unknown;
26
+ } | null | undefined, active: ActiveNetworkTask | null): OutboundRewrite;
27
+ /** outbound-only 模式下模型不能自选 high(#1770 第三条):降为 normal,其余原样。 */
28
+ export declare function clampOutboundPriority(priority: unknown, outboundOnly: boolean): "high" | "normal" | "low" | undefined;
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Resolve one batch workdir before any mkdir/chdir loop starts.
3
+ *
4
+ * Node does not expand shell tildes. Leaving `~/team` relative means every
5
+ * iteration can resolve it from the previous node's cwd and create paths such
6
+ * as `/work/~/team/~/team`. Only the current user's `~` form is supported;
7
+ * `~other` is rejected instead of being written as a literal directory.
8
+ */
9
+ export declare function normalizeBatchWorkdir(input: string, cwd?: string, home?: string): string;
@@ -0,0 +1,13 @@
1
+ export interface BootstrapPasswordUpdateInvocation {
2
+ argv: string[];
3
+ env: NodeJS.ProcessEnv;
4
+ script: string;
5
+ }
6
+ /**
7
+ * Resolve the database selected for the local Hub into an explicit absolute
8
+ * path before launching the bootstrap helper. The helper must never infer a
9
+ * database from its own HOME/cwd: those can differ from the parent process.
10
+ */
11
+ export declare function resolveBootstrapDatabasePath(env: NodeJS.ProcessEnv, home: string, cwd: string): string;
12
+ export declare const BOOTSTRAP_PASSWORD_UPDATE_SCRIPT: string;
13
+ export declare function buildBootstrapPasswordUpdateInvocation(userId: string, dbPath: string, baseEnv?: NodeJS.ProcessEnv): BootstrapPasswordUpdateInvocation;
@@ -0,0 +1,29 @@
1
+ interface AttachmentDescriptor {
2
+ type?: unknown;
3
+ file_id?: unknown;
4
+ path?: unknown;
5
+ mime?: unknown;
6
+ name?: unknown;
7
+ size?: unknown;
8
+ }
9
+ export interface ChannelAttachmentDeps {
10
+ hubUrl: string;
11
+ authToken: string;
12
+ cacheDir: string;
13
+ fetch?: typeof fetch;
14
+ maxBytes?: number;
15
+ }
16
+ export interface ChannelAttachmentResult {
17
+ paths: string[];
18
+ failures: Array<{
19
+ fileId: string;
20
+ code: string;
21
+ message: string;
22
+ }>;
23
+ }
24
+ export declare function readableAttachmentsFromInbox(message: any): AttachmentDescriptor[];
25
+ export declare function channelAttachmentCacheDir(home: string, alias: string): string;
26
+ export declare function downloadChannelAttachments(message: any, deps: ChannelAttachmentDeps): Promise<ChannelAttachmentResult>;
27
+ export declare const downloadChannelImageAttachments: typeof downloadChannelAttachments;
28
+ export declare function appendChannelAttachmentPaths(content: string, paths: readonly string[]): string;
29
+ export {};
@@ -0,0 +1,10 @@
1
+ /** One inbound inbox row → the meta Claude Code renders as `<channel …>` attrs.
2
+ *
3
+ * Pure so the attribute set is assertable; it used to be inline in the SSE
4
+ * handler, where nothing could see it. */
5
+ export declare function inboundChannelMeta(msg: {
6
+ id: string;
7
+ from_session?: string | null;
8
+ priority?: string | null;
9
+ created_at?: string | null;
10
+ }): Record<string, string>;
@@ -0,0 +1,14 @@
1
+ export declare function sendChannelTaskWithTrace(input: {
2
+ alias: string;
3
+ task: string;
4
+ priority?: string;
5
+ fromAlias: string;
6
+ networkId?: string | null;
7
+ /** Structured task metadata forwarded verbatim, e.g. { attachments: [...] }.
8
+ * Omitted from the outbound body when absent, so a call without it is
9
+ * unchanged. */
10
+ meta?: Record<string, unknown>;
11
+ }, deps: {
12
+ send: (args: Record<string, unknown>) => Promise<any>;
13
+ log: (line: string) => void;
14
+ }): Promise<any>;
@@ -0,0 +1,28 @@
1
+ export declare const CLAUDE_VENDOR_ENV_KEYS: readonly ["ANTHROPIC_BASE_URL", "ANTHROPIC_AUTH_TOKEN", "ANTHROPIC_API_KEY"];
2
+ export type PlainSecretEnvRewrite = {
3
+ key: string;
4
+ refName: string;
5
+ value: string;
6
+ };
7
+ /**
8
+ * Plan the values that the node-create writer will move into its line-oriented
9
+ * `.env` file. This is deliberately side-effect free: callers can run it as a
10
+ * preflight before creating a node directory, changing process.env, or writing
11
+ * config.json. Keeping the line-break rejection here makes it cover every
12
+ * caller of the dotenv writer, including the no-name interactive wizard.
13
+ */
14
+ export declare function planPlainSecretEnvRewrites(input: {
15
+ env: unknown;
16
+ nodeId: string;
17
+ }): PlainSecretEnvRewrite[];
18
+ /**
19
+ * Persist the exact Anthropic-compatible vendor environment used by an
20
+ * explicit claude-agent-sdk create. Explicit --env values retain precedence;
21
+ * ambient shell values only fill missing known keys. Other environment values
22
+ * are intentionally ignored so node create never snapshots the whole shell.
23
+ */
24
+ export declare function collectClaudeVendorEnvForCreate(input: {
25
+ runtime: string;
26
+ explicitEnv: readonly string[];
27
+ shellEnv: Readonly<Record<string, string | undefined>>;
28
+ }): string[];
@@ -0,0 +1,8 @@
1
+ export type ParsedCliOptions = {
2
+ [key: string]: string | string[];
3
+ _channels: string[];
4
+ _envs: string[];
5
+ };
6
+ export declare const BOOLEAN_FLAGS: Set<string>;
7
+ export declare function parseCliOptions(argv: string[]): ParsedCliOptions;
8
+ export declare function positionalArgs(argv: string[]): string[];
@@ -0,0 +1,16 @@
1
+ /**
2
+ * #1645 —— `anet doctor` 原先对三个 runtime CLI **只检查「在不在」**:
3
+ *
4
+ * try { execSync("codex --version", …); check("Codex CLI", true); } catch { … }
5
+ *
6
+ * 于是一个**装着、但太旧**的 CLI 会拿到一个 ✅。实测过一次:`codex-cli 0.149.1`
7
+ * 解不动上游 models 响应(`unknown variant \`max\``,它只认到 `xhigh`),
8
+ * rmcp worker 致命退出,用户看到的是 300s 超时 —— 而 doctor 说一切正常。
9
+ *
10
+ * 🔴 **这里只把版本摆出来,不做最低版本判定。**
11
+ * 「多少版本才够」由上游返回什么决定,不是我们能钉死的常量;猜一个下限,
12
+ * 会在别人升级 CLI、上游又改动之后变成误报。而一个会误报的检查,
13
+ * 第一周就会被人关掉。摆出实际版本,让读的人自己对得上号,是这一格
14
+ * 现在能诚实做到的全部。
15
+ */
16
+ export declare function formatCliVersion(raw: unknown): string;
@@ -0,0 +1,9 @@
1
+ export declare function sendClientTaskWithTrace(input: {
2
+ alias: string;
3
+ fromAlias: string;
4
+ parentTaskId?: string | null;
5
+ networkId?: string | null;
6
+ }, dependencies: {
7
+ send: () => Promise<any>;
8
+ log: (line: string) => void;
9
+ }): Promise<any>;
@@ -1 +1 @@
1
- const a0_0x4059a6=a0_0x27f5;(function(_0x15cdca,_0x33c5b4){const _0x478268=a0_0x27f5,_0x51f030=_0x15cdca();while(!![]){try{const _0x2214d1=parseInt(_0x478268(0x1ee))/0x1+-parseInt(_0x478268(0x1d6))/0x2*(-parseInt(_0x478268(0x1db))/0x3)+parseInt(_0x478268(0x210))/0x4*(parseInt(_0x478268(0x1d4))/0x5)+parseInt(_0x478268(0x206))/0x6+-parseInt(_0x478268(0x1d2))/0x7+parseInt(_0x478268(0x1e9))/0x8*(parseInt(_0x478268(0x1dd))/0x9)+-parseInt(_0x478268(0x1da))/0xa;if(_0x2214d1===_0x33c5b4)break;else _0x51f030['push'](_0x51f030['shift']());}catch(_0x241b90){_0x51f030['push'](_0x51f030['shift']());}}}(a0_0x59e0,0x3f187));import{EventEmitter as a0_0x535c0e}from'events';import{hostname as a0_0x8960f3}from'os';class T extends a0_0x535c0e{[a0_0x4059a6(0x1f2)];[a0_0x4059a6(0x1e1)];[a0_0x4059a6(0x1f9)];[a0_0x4059a6(0x1ff)];['resumeId'];[a0_0x4059a6(0x1f1)];[a0_0x4059a6(0x209)];[a0_0x4059a6(0x211)];['sseAbort'];[a0_0x4059a6(0x1ce)]=!0x1;constructor(_0x332b50){const _0x1d936b=a0_0x4059a6;super();if(this[_0x1d936b(0x1f2)]=_0x332b50['url'][_0x1d936b(0x200)](/\/$/,''),this[_0x1d936b(0x1e1)]=_0x332b50['alias'],this[_0x1d936b(0x1f9)]=_0x332b50[_0x1d936b(0x1f9)],this[_0x1d936b(0x1ff)]=_0x332b50['agent']||_0x1d936b(0x1de),this[_0x1d936b(0x203)]=_0x1d936b(0x1d9)+_0x332b50[_0x1d936b(0x1e1)]+'-'+Date['now']()[_0x1d936b(0x1ca)](0x24),this['heartbeatInterval']=_0x332b50[_0x1d936b(0x1f1)]??0x2bf20,this[_0x1d936b(0x209)]=_0x332b50[_0x1d936b(0x209)]??0xbb8,_0x332b50[_0x1d936b(0x1eb)]!==!0x1)this[_0x1d936b(0x1d7)]();}[a0_0x4059a6(0x1e0)](_0x295217){const _0x5d9e3c=a0_0x4059a6;console[_0x5d9e3c(0x1e0)]('['+new Date()[_0x5d9e3c(0x20b)]()[_0x5d9e3c(0x1fd)](0x0,0x8)+_0x5d9e3c(0x1f0)+this[_0x5d9e3c(0x1e1)]+']\x20'+_0x295217);}async['call'](_0x311ad1,_0x4838d7){const _0x52ef0a=a0_0x4059a6;let _0x248b99={'Content-Type':_0x52ef0a(0x1f8),'Accept':_0x52ef0a(0x208)};if(this[_0x52ef0a(0x1f9)])_0x248b99[_0x52ef0a(0x1df)]=_0x52ef0a(0x204)+this[_0x52ef0a(0x1f9)];let _0x2059d2=await(await fetch(this[_0x52ef0a(0x1f2)]+_0x52ef0a(0x1e5),{'method':'POST','headers':_0x248b99,'body':JSON[_0x52ef0a(0x20a)]({'jsonrpc':'2.0','id':Date[_0x52ef0a(0x1e6)](),'method':_0x52ef0a(0x1c4),'params':{'name':_0x311ad1,'arguments':_0x4838d7}})}))[_0x52ef0a(0x1c9)](),_0x26c4a1=_0x2059d2[_0x52ef0a(0x1d1)](/data: (.+)/),_0x5a1078=_0x26c4a1?JSON[_0x52ef0a(0x1ef)](_0x26c4a1[0x1]):JSON['parse'](_0x2059d2),_0x38fd28=_0x5a1078?.[_0x52ef0a(0x1e4)]?.[_0x52ef0a(0x1cc)]?.[0x0]?.[_0x52ef0a(0x1c9)];return _0x38fd28?JSON[_0x52ef0a(0x1ef)](_0x38fd28):_0x5a1078;}async['connect'](){const _0x480e05=a0_0x4059a6;if(this['running'])return;this[_0x480e05(0x1ce)]=!0x0,await this[_0x480e05(0x1cd)](_0x480e05(0x1c2)),this[_0x480e05(0x1e0)]('registered'),this['heartbeatTimer']=setInterval(()=>{const _0x93e01c=_0x480e05;this[_0x93e01c(0x1cd)](_0x93e01c(0x1c2))[_0x93e01c(0x202)](_0x46ccbd=>this[_0x93e01c(0x1e0)]('heartbeat\x20failed:\x20'+_0x46ccbd[_0x93e01c(0x20f)]));},this[_0x480e05(0x1f1)]),this['connectSSE']();}async[a0_0x4059a6(0x1c1)](){const _0x1691e2=a0_0x4059a6;if(this['running']=!0x1,this['sseAbort']?.[_0x1691e2(0x1fe)](),this[_0x1691e2(0x211)])clearInterval(this[_0x1691e2(0x211)]);await this[_0x1691e2(0x1cd)]('offline')['catch'](()=>{}),this[_0x1691e2(0x1e0)](_0x1691e2(0x1fa));}async[a0_0x4059a6(0x1f6)](_0x27993b,_0x26abfd,_0xb43d11=a0_0x4059a6(0x1dc)){const _0x81460d=a0_0x4059a6;return this[_0x81460d(0x207)](_0x81460d(0x1cf),{'alias':_0x27993b,'task':_0x26abfd,'priority':_0xb43d11,'from_session':this[_0x81460d(0x1e1)]});}async['message'](_0x1c53a4,_0x2689bc){const _0xa4a523=a0_0x4059a6;return this[_0xa4a523(0x207)]('send_message',{'alias':_0x1c53a4,'message':_0x2689bc,'from_session':this['alias']});}async[a0_0x4059a6(0x1e2)](_0x50f553,_0x14ad02,_0x2a5143='completed'){const _0x36edf1=a0_0x4059a6;return this[_0x36edf1(0x207)]('send_reply',{'in_reply_to':_0x50f553,'text':_0x14ad02,'status':_0x2a5143});}async[a0_0x4059a6(0x1cd)](_0x80a390,_0x451e24){const _0x3c7df5=a0_0x4059a6;return this['call']('report_status',{'resume_id':this[_0x3c7df5(0x203)],'alias':this[_0x3c7df5(0x1e1)],'status':_0x80a390,'server':a0_0x8960f3(),'hostname':a0_0x8960f3(),'agent':this['agent'],'project_dir':process[_0x3c7df5(0x1c6)](),..._0x451e24});}async[a0_0x4059a6(0x1d5)](){const _0x1737ef=a0_0x4059a6;return this[_0x1737ef(0x207)](_0x1737ef(0x1f3),{});}async[a0_0x4059a6(0x20d)](_0x4b87de,_0x68abd2){const _0x18faab=a0_0x4059a6;return this['call'](_0x18faab(0x20d),{'message':_0x4b87de,'filter_server':_0x68abd2?.['server'],'filter_status':_0x68abd2?.[_0x18faab(0x1cd)]});}async['connectSSE'](){const _0x49128a=a0_0x4059a6;let _0x1575e4=encodeURIComponent(this['alias']),_0xc8d3ba=this[_0x49128a(0x1f2)]+'/events/'+_0x1575e4,_0x5e1288=this[_0x49128a(0x209)];while(this['running']){try{this['sseAbort']=new AbortController();let _0x19f575={'Accept':_0x49128a(0x1ea)};if(this['token'])_0x19f575[_0x49128a(0x1df)]='Bearer\x20'+this['token'];let _0x24d6f5=await fetch(_0xc8d3ba,{'headers':_0x19f575,'signal':this[_0x49128a(0x1fb)][_0x49128a(0x205)]});if(!_0x24d6f5['ok']||!_0x24d6f5['body']){this[_0x49128a(0x1e0)](_0x49128a(0x201)+_0x24d6f5[_0x49128a(0x1cd)]),await this[_0x49128a(0x1fc)](_0x5e1288),_0x5e1288=Math[_0x49128a(0x1c5)](_0x5e1288*1.5,0xea60);continue;}_0x5e1288=this[_0x49128a(0x209)];let _0x5c3cf4=_0x24d6f5['body'][_0x49128a(0x1d0)](),_0x1caacd=new TextDecoder(),_0x486e6e='';while(this['running']){let {done:_0x1d8055,value:_0x4606df}=await _0x5c3cf4[_0x49128a(0x1c3)]();if(_0x1d8055)break;_0x486e6e+=_0x1caacd['decode'](_0x4606df,{'stream':!0x0});let _0xad8b1=_0x486e6e['split']('\x0a');_0x486e6e=_0xad8b1[_0x49128a(0x1d8)]()||'';for(let _0x5cc51a of _0xad8b1){if(!_0x5cc51a[_0x49128a(0x20e)](_0x49128a(0x1f7)))continue;try{let _0x5081d2=JSON['parse'](_0x5cc51a[_0x49128a(0x1fd)](0x6));if(_0x5081d2[_0x49128a(0x1ec)]===_0x49128a(0x1cb)){this[_0x49128a(0x1e0)](_0x49128a(0x1c8)),this[_0x49128a(0x1d3)](_0x49128a(0x1cb));continue;}if(_0x5081d2[_0x49128a(0x1ec)]==='new_task'||_0x5081d2['type']===_0x49128a(0x1e3)||_0x5081d2[_0x49128a(0x1ec)]===_0x49128a(0x20d))await this[_0x49128a(0x1f4)]();}catch{}}}}catch(_0x9f64eb){if(_0x9f64eb['name']==='AbortError')break;this[_0x49128a(0x1d3)]('error',_0x9f64eb),this[_0x49128a(0x1e0)](_0x49128a(0x1e7)+_0x9f64eb[_0x49128a(0x20f)]);}if(this['running'])this[_0x49128a(0x1d3)](_0x49128a(0x1fa)),this[_0x49128a(0x1e0)](_0x49128a(0x1ed)+_0x5e1288/0x3e8+_0x49128a(0x1f5)),await this[_0x49128a(0x1fc)](_0x5e1288),_0x5e1288=Math['min'](_0x5e1288*1.5,0xea60);}}async['processInbox'](){const _0x3f58b6=a0_0x4059a6;try{let _0x565345=(await this[_0x3f58b6(0x207)](_0x3f58b6(0x1c7),{'alias':this[_0x3f58b6(0x1e1)],'limit':0xa}))?.['messages']||[];for(let _0x2ec321 of _0x565345)await this['call'](_0x3f58b6(0x20c),{'alias':this[_0x3f58b6(0x1e1)],'message_id':_0x2ec321['id']}),this['log']('←\x20'+_0x2ec321['from_session']+':\x20'+_0x2ec321[_0x3f58b6(0x1cc)]['slice'](0x0,0x3c)),this[_0x3f58b6(0x1d3)]('task',_0x2ec321),this[_0x3f58b6(0x1d3)]('message',_0x2ec321);}catch(_0x54eb28){this[_0x3f58b6(0x1e0)](_0x3f58b6(0x1e8)+_0x54eb28[_0x3f58b6(0x20f)]);}}[a0_0x4059a6(0x1fc)](_0x59d1f3){return new Promise(_0x175e80=>setTimeout(_0x175e80,_0x59d1f3));}}function a0_0x27f5(_0x46f7fb,_0x5cfedd){_0x46f7fb=_0x46f7fb-0x1c1;const _0x59e05e=a0_0x59e0();let _0x27f5cf=_0x59e05e[_0x46f7fb];return _0x27f5cf;}var $=T;export{$ as default,T as CommHub};function a0_0x59e0(){const _0x18b957=['12MZNXgz','heartbeatTimer','disconnect','idle','read','tools/call','min','cwd','get_inbox','SSE\x20connected','text','toString','connected','content','status','running','send_task','getReader','match','1724037tyLDEM','emit','87585gvKJbd','getAllStatus','42892KhZtrm','connect','pop','sdk-','6010190EZalRW','21nTlVZe','normal','9xUexcv','sdk','Authorization','log','alias','reply','new_message','result','/mcp','now','SSE\x20error:\x20','inbox\x20error:\x20','1390168FnahBL','text/event-stream','autoConnect','type','SSE\x20reconnecting\x20in\x20','427813GXMJxk','parse',']\x20[commhub:','heartbeatInterval','url','get_all_status','processInbox','s...','send','data:\x20','application/json','token','disconnected','sseAbort','sleep','slice','abort','agent','replace','SSE\x20failed:\x20','catch','resumeId','Bearer\x20','signal','1808952fKTtBp','call','application/json,\x20text/event-stream','reconnectDelay','stringify','toTimeString','ack_inbox','broadcast','startsWith','message'];a0_0x59e0=function(){return _0x18b957;};return a0_0x59e0();}
1
+ function a0_0x3382(){const _0xea0559=['SSE\x20failed:\x20','get_all_status','alias','abort','task.started','\x20duration_ms=','type','SSE\x20error:\x20','send','disconnected','data:\x20','AbortError','from_alias','615156FSeCEu','catch','s...','offline','heartbeatInterval','min','replace','text/event-stream','processInbox','\x20parent_task_id=','content','network_id','transport','parent_task_id','running','sseAbort','tools/call','connected','error','autoConnect','<pending>','application/json','CommHub\x20response\x20omitted\x20task_id','sleep','1723156XqVmlz','15794001rlVHYF','connectSSE','report_status','to_alias','new_message','task','broadcast','78qkZQEO','Authorization','\x20from=','cwd','task.expired','reconnectDelay','8568959otsEhV','slice','message','<unknown>','Bearer\x20','registered','SSE\x20reconnecting\x20in\x20','call','task.ack','signal','[REDACTED]','connect','fromAlias','application/json,\x20text/event-stream','\x20task_id=','\x20transport=','token','message_id','[commhub:task]\x20','missing_task_id','agent','inbox\x20error:\x20','6880405jcVnQQ','match','normal','5431482VZAhXy','2.0','\x20network_id=','/mcp','status','toTimeString','now','split','task_id','text','read','mcp_http','ack_inbox','parse','failed','startsWith','reply',']\x20[commhub:','POST','server','8hqXtQN','<missing>','getAllStatus','\x20to=','name','delivered','resumeId','unknown\x20error','97580CTmIxV','heartbeatTimer','send_failed','error_code','\x20error=','getReader','error_message','pop','send_task','get_inbox','disconnect','task.send.start','url','log','task.send.delivered','CommHub\x20rejected\x20task','emit','body','completed','stringify','duration_ms','string'];a0_0x3382=function(){return _0xea0559;};return a0_0x3382();}const a0_0x27e4e3=a0_0x1e42;function a0_0x1e42(_0xf905eb,_0x779b8d){_0xf905eb=_0xf905eb-0x12a;const _0x3382e0=a0_0x3382();let _0x1e4297=_0x3382e0[_0xf905eb];return _0x1e4297;}(function(_0x90da6,_0x3e6638){const _0x36ca51=a0_0x1e42,_0x20cd61=_0x90da6();while(!![]){try{const _0x562b6b=-parseInt(_0x36ca51(0x198))/0x1+-parseInt(_0x36ca51(0x132))/0x2+parseInt(_0x36ca51(0x13a))/0x3*(parseInt(_0x36ca51(0x175))/0x4)+parseInt(_0x36ca51(0x156))/0x5+parseInt(_0x36ca51(0x159))/0x6+parseInt(_0x36ca51(0x140))/0x7+parseInt(_0x36ca51(0x16d))/0x8*(-parseInt(_0x36ca51(0x133))/0x9);if(_0x562b6b===_0x3e6638)break;else _0x20cd61['push'](_0x20cd61['shift']());}catch(_0x21f0e5){_0x20cd61['push'](_0x20cd61['shift']());}}}(a0_0x3382,0xddb50));import{EventEmitter as a0_0x542b01}from'events';import{hostname as a0_0x4e6936}from'os';var K=/(?:atok|ntok|utok|ghp|github_pat)_[A-Za-z0-9_-]+|Bearer\s+\S+/gi,L=(_0xd41c9c,_0x182e26)=>(_0xd41c9c??_0x182e26)[a0_0x27e4e3(0x19e)](/[\r\n\x00-\x1f\x7f]/g,'\x20')['slice'](0x0,0xf0);function N(_0x467dfc){const _0x95e0ae=a0_0x27e4e3;return(_0x467dfc instanceof Error?_0x467dfc[_0x95e0ae(0x142)]:String(_0x467dfc??_0x95e0ae(0x174)))[_0x95e0ae(0x19e)](K,_0x95e0ae(0x14a))['replace'](/[\r\n\x00-\x1f\x7f]/g,'\x20')[_0x95e0ae(0x141)](0x0,0xf0);}function O(_0x1fe4e9,_0x5b6f2d=process.env.ANET_TASK_TRACE_FORMAT==='json'){const _0x2037b8=a0_0x27e4e3;if(_0x5b6f2d)return JSON[_0x2037b8(0x188)](_0x1fe4e9);let _0x478d57=L(_0x1fe4e9[_0x2037b8(0x1a5)],_0x2037b8(0x16e)),_0x3273e3=L(_0x1fe4e9['task_id'],_0x2037b8(0x12e)),_0x36f482=_0x1fe4e9[_0x2037b8(0x178)]?_0x2037b8(0x179)+_0x1fe4e9['error_code']+':'+(_0x1fe4e9[_0x2037b8(0x17b)]??''):'';return _0x2037b8(0x152)+_0x1fe4e9[_0x2037b8(0x15d)]+_0x2037b8(0x13c)+L(_0x1fe4e9[_0x2037b8(0x197)],_0x2037b8(0x143))+_0x2037b8(0x170)+L(_0x1fe4e9[_0x2037b8(0x136)],_0x2037b8(0x143))+_0x2037b8(0x14e)+_0x3273e3+_0x2037b8(0x1a1)+_0x478d57+_0x2037b8(0x15b)+L(_0x1fe4e9[_0x2037b8(0x1a3)],_0x2037b8(0x143))+_0x2037b8(0x14f)+_0x1fe4e9['transport']+_0x2037b8(0x190)+_0x1fe4e9[_0x2037b8(0x189)]+'\x20lifecycle='+_0x1fe4e9['lifecycle_tracking']+_0x36f482;}function U(_0x5f36ca){const _0x480a19=a0_0x27e4e3;return{'event':{'sending':_0x480a19(0x180),'delivered':_0x480a19(0x183),'failed':'task.send.failed','acked':_0x480a19(0x148),'started':_0x480a19(0x18f),'replied':'task.replied','expired':_0x480a19(0x13e)}[_0x5f36ca[_0x480a19(0x15d)]],..._0x5f36ca};}function j(_0x256d22){const _0x32f770=a0_0x27e4e3;let _0x29aa0d=_0x256d22?.[_0x32f770(0x161)]||_0x256d22?.[_0x32f770(0x151)]||_0x256d22?.['id'];if(_0x29aa0d)return String(_0x29aa0d);let _0x3ee371=_0x256d22?.['content']?.[0x0]?.[_0x32f770(0x162)];if(typeof _0x3ee371!==_0x32f770(0x18a))return null;try{let _0x2ff83b=JSON[_0x32f770(0x166)](_0x3ee371);return _0x2ff83b?.[_0x32f770(0x161)]||_0x2ff83b?.[_0x32f770(0x151)]||_0x2ff83b?.['id']||null;}catch{return null;}}async function X(_0x52d832,_0x2485e7){const _0x573433=a0_0x27e4e3;let _0x198397=_0x2485e7[_0x573433(0x15f)]??Date[_0x573433(0x15f)],_0x4ac56e=_0x198397(),_0x129730=(_0x476382,_0xaee3ff,_0x43cbc7,_0x3c4187)=>{const _0x2cae9a=_0x573433;_0x2485e7['log'](O(U({'from_alias':_0x52d832[_0x2cae9a(0x14c)],'to_alias':_0x52d832['toAlias'],'task_id':_0xaee3ff,'parent_task_id':_0x52d832['parentTaskId'],'network_id':_0x52d832['networkId'],'transport':_0x52d832[_0x2cae9a(0x1a4)],'status':_0x476382,'duration_ms':_0x198397()-_0x4ac56e,'lifecycle_tracking':_0x52d832['lifecycleTracking'],..._0x43cbc7!==void 0x0?{'error_code':_0x3c4187||_0x2cae9a(0x177),'error_message':N(_0x43cbc7)}:{}})));};_0x129730('sending',null);try{let _0x30edb7=await _0x2485e7['send'](),_0x5ba6a8=j(_0x30edb7);if(_0x5ba6a8)_0x129730(_0x573433(0x172),_0x5ba6a8);else{if(_0x30edb7?.['ok']===!0x1||_0x30edb7?.[_0x573433(0x12c)])_0x129730(_0x573433(0x167),_0x5ba6a8,_0x30edb7?.['error']||_0x573433(0x184),'send_rejected');else _0x129730('failed',null,_0x573433(0x130),_0x573433(0x153));}return _0x30edb7;}catch(_0x29d035){throw _0x129730(_0x573433(0x167),null,_0x29d035,_0x573433(0x177)),_0x29d035;}}async function Y(_0xe417af,_0x359cab){const _0x4fe36a=a0_0x27e4e3;return X({'fromAlias':_0xe417af[_0x4fe36a(0x14c)],'toAlias':_0xe417af['alias'],'parentTaskId':_0xe417af['parentTaskId']||null,'networkId':_0xe417af['networkId']||null,'transport':_0x4fe36a(0x164),'lifecycleTracking':'not_tracked'},_0x359cab);}class $ extends a0_0x542b01{['url'];[a0_0x27e4e3(0x18d)];['token'];['agent'];[a0_0x27e4e3(0x173)];['heartbeatInterval'];[a0_0x27e4e3(0x13f)];[a0_0x27e4e3(0x176)];[a0_0x27e4e3(0x1a7)];[a0_0x27e4e3(0x1a6)]=!0x1;constructor(_0x47a35f){const _0x175230=a0_0x27e4e3;super();if(this[_0x175230(0x181)]=_0x47a35f[_0x175230(0x181)][_0x175230(0x19e)](/\/$/,''),this[_0x175230(0x18d)]=_0x47a35f['alias'],this[_0x175230(0x150)]=_0x47a35f['token'],this[_0x175230(0x154)]=_0x47a35f['agent']||'sdk',this[_0x175230(0x173)]='sdk-'+_0x47a35f[_0x175230(0x18d)]+'-'+Date[_0x175230(0x15f)]()['toString'](0x24),this[_0x175230(0x19c)]=_0x47a35f[_0x175230(0x19c)]??0x2bf20,this['reconnectDelay']=_0x47a35f[_0x175230(0x13f)]??0xbb8,_0x47a35f[_0x175230(0x12d)]!==!0x1)this[_0x175230(0x14b)]();}['log'](_0x143e0c){const _0x2563ab=a0_0x27e4e3;console['log']('['+new Date()[_0x2563ab(0x15e)]()[_0x2563ab(0x141)](0x0,0x8)+_0x2563ab(0x16a)+this[_0x2563ab(0x18d)]+']\x20'+_0x143e0c);}async[a0_0x27e4e3(0x147)](_0x4e3448,_0x368953){const _0x225fc6=a0_0x27e4e3;let _0x12b58d={'Content-Type':_0x225fc6(0x12f),'Accept':_0x225fc6(0x14d)};if(this[_0x225fc6(0x150)])_0x12b58d[_0x225fc6(0x13b)]=_0x225fc6(0x144)+this[_0x225fc6(0x150)];let _0x4e4719=await(await fetch(this[_0x225fc6(0x181)]+_0x225fc6(0x15c),{'method':_0x225fc6(0x16b),'headers':_0x12b58d,'body':JSON[_0x225fc6(0x188)]({'jsonrpc':_0x225fc6(0x15a),'id':Date[_0x225fc6(0x15f)](),'method':_0x225fc6(0x12a),'params':{'name':_0x4e3448,'arguments':_0x368953}})}))[_0x225fc6(0x162)](),_0x35c021=_0x4e4719[_0x225fc6(0x157)](/data: (.+)/),_0x1ca6f3=_0x35c021?JSON['parse'](_0x35c021[0x1]):JSON[_0x225fc6(0x166)](_0x4e4719),_0x346011=_0x1ca6f3?.['result']?.['content']?.[0x0]?.['text'];return _0x346011?JSON[_0x225fc6(0x166)](_0x346011):_0x1ca6f3;}async[a0_0x27e4e3(0x14b)](){const _0x52f34f=a0_0x27e4e3;if(this[_0x52f34f(0x1a6)])return;this['running']=!0x0,await this[_0x52f34f(0x15d)]('idle'),this['log'](_0x52f34f(0x145)),this['heartbeatTimer']=setInterval(()=>{const _0x4ffac7=_0x52f34f;this[_0x4ffac7(0x15d)]('idle')[_0x4ffac7(0x199)](_0x39cf5f=>this[_0x4ffac7(0x182)]('heartbeat\x20failed:\x20'+_0x39cf5f[_0x4ffac7(0x142)]));},this['heartbeatInterval']),this[_0x52f34f(0x134)]();}async[a0_0x27e4e3(0x17f)](){const _0x26df7f=a0_0x27e4e3;if(this[_0x26df7f(0x1a6)]=!0x1,this[_0x26df7f(0x1a7)]?.[_0x26df7f(0x18e)](),this[_0x26df7f(0x176)])clearInterval(this[_0x26df7f(0x176)]);await this[_0x26df7f(0x15d)](_0x26df7f(0x19b))[_0x26df7f(0x199)](()=>{}),this[_0x26df7f(0x182)](_0x26df7f(0x194));}async[a0_0x27e4e3(0x193)](_0x1dba3f,_0x52e665,_0x199b24=a0_0x27e4e3(0x158)){const _0x57d499=a0_0x27e4e3;return Y({'alias':_0x1dba3f,'fromAlias':this[_0x57d499(0x18d)]},{'log':_0x285353=>console['log'](_0x285353),'send':()=>this[_0x57d499(0x147)](_0x57d499(0x17d),{'alias':_0x1dba3f,'task':_0x52e665,'priority':_0x199b24,'from_session':this[_0x57d499(0x18d)]})});}async[a0_0x27e4e3(0x142)](_0x45e0c9,_0x23c08e){const _0x257c5b=a0_0x27e4e3;return this[_0x257c5b(0x147)]('send_message',{'alias':_0x45e0c9,'message':_0x23c08e,'from_session':this[_0x257c5b(0x18d)]});}async[a0_0x27e4e3(0x169)](_0x5d6985,_0xc2b49a,_0x3c4097=a0_0x27e4e3(0x187)){const _0x5db0db=a0_0x27e4e3;return this[_0x5db0db(0x147)]('send_reply',{'in_reply_to':_0x5d6985,'text':_0xc2b49a,'status':_0x3c4097});}async['status'](_0x224fad,_0x20c9bc){const _0x5021ac=a0_0x27e4e3;return this[_0x5021ac(0x147)](_0x5021ac(0x135),{'resume_id':this['resumeId'],'alias':this[_0x5021ac(0x18d)],'status':_0x224fad,'server':a0_0x4e6936(),'hostname':a0_0x4e6936(),'agent':this[_0x5021ac(0x154)],'project_dir':process[_0x5021ac(0x13d)](),..._0x20c9bc});}async[a0_0x27e4e3(0x16f)](){const _0x3d86a9=a0_0x27e4e3;return this['call'](_0x3d86a9(0x18c),{});}async[a0_0x27e4e3(0x139)](_0x227c4d,_0x4f718c){const _0x274cb4=a0_0x27e4e3;return this[_0x274cb4(0x147)](_0x274cb4(0x139),{'message':_0x227c4d,'filter_server':_0x4f718c?.[_0x274cb4(0x16c)],'filter_status':_0x4f718c?.[_0x274cb4(0x15d)]});}async[a0_0x27e4e3(0x134)](){const _0x573bb9=a0_0x27e4e3;let _0x59b837=encodeURIComponent(this['alias']),_0xc4b6a8=this[_0x573bb9(0x181)]+'/events/'+_0x59b837,_0x210804=this['reconnectDelay'];while(this[_0x573bb9(0x1a6)]){try{this[_0x573bb9(0x1a7)]=new AbortController();let _0x5814c0={'Accept':_0x573bb9(0x19f)};if(this['token'])_0x5814c0[_0x573bb9(0x13b)]=_0x573bb9(0x144)+this[_0x573bb9(0x150)];let _0x514cde=await fetch(_0xc4b6a8,{'headers':_0x5814c0,'signal':this[_0x573bb9(0x1a7)][_0x573bb9(0x149)]});if(!_0x514cde['ok']||!_0x514cde[_0x573bb9(0x186)]){this['log'](_0x573bb9(0x18b)+_0x514cde[_0x573bb9(0x15d)]),await this[_0x573bb9(0x131)](_0x210804),_0x210804=Math[_0x573bb9(0x19d)](_0x210804*1.5,0xea60);continue;}_0x210804=this[_0x573bb9(0x13f)];let _0x26fe44=_0x514cde['body'][_0x573bb9(0x17a)](),_0x98b346=new TextDecoder(),_0x1edf3b='';while(this[_0x573bb9(0x1a6)]){let {done:_0x27f79b,value:_0x1b5147}=await _0x26fe44[_0x573bb9(0x163)]();if(_0x27f79b)break;_0x1edf3b+=_0x98b346['decode'](_0x1b5147,{'stream':!0x0});let _0x576a7e=_0x1edf3b[_0x573bb9(0x160)]('\x0a');_0x1edf3b=_0x576a7e[_0x573bb9(0x17c)]()||'';for(let _0x4e2b06 of _0x576a7e){if(!_0x4e2b06[_0x573bb9(0x168)](_0x573bb9(0x195)))continue;try{let _0x3ce523=JSON[_0x573bb9(0x166)](_0x4e2b06[_0x573bb9(0x141)](0x6));if(_0x3ce523['type']===_0x573bb9(0x12b)){this[_0x573bb9(0x182)]('SSE\x20connected'),this['emit'](_0x573bb9(0x12b));continue;}if(_0x3ce523[_0x573bb9(0x191)]==='new_task'||_0x3ce523[_0x573bb9(0x191)]===_0x573bb9(0x137)||_0x3ce523[_0x573bb9(0x191)]===_0x573bb9(0x139))await this[_0x573bb9(0x1a0)]();}catch{}}}}catch(_0x4e6e0f){if(_0x4e6e0f[_0x573bb9(0x171)]===_0x573bb9(0x196))break;this[_0x573bb9(0x185)](_0x573bb9(0x12c),_0x4e6e0f),this[_0x573bb9(0x182)](_0x573bb9(0x192)+_0x4e6e0f['message']);}if(this[_0x573bb9(0x1a6)])this[_0x573bb9(0x185)](_0x573bb9(0x194)),this['log'](_0x573bb9(0x146)+_0x210804/0x3e8+_0x573bb9(0x19a)),await this[_0x573bb9(0x131)](_0x210804),_0x210804=Math[_0x573bb9(0x19d)](_0x210804*1.5,0xea60);}}async[a0_0x27e4e3(0x1a0)](){const _0x497900=a0_0x27e4e3;try{let _0x1208ed=(await this[_0x497900(0x147)](_0x497900(0x17e),{'alias':this[_0x497900(0x18d)],'limit':0xa}))?.['messages']||[];for(let _0x25d0c0 of _0x1208ed)await this[_0x497900(0x147)](_0x497900(0x165),{'alias':this[_0x497900(0x18d)],'message_id':_0x25d0c0['id']}),this[_0x497900(0x182)]('←\x20'+_0x25d0c0['from_session']+':\x20'+_0x25d0c0[_0x497900(0x1a2)][_0x497900(0x141)](0x0,0x3c)),this[_0x497900(0x185)](_0x497900(0x138),_0x25d0c0),this[_0x497900(0x185)](_0x497900(0x142),_0x25d0c0);}catch(_0x36ea44){this['log'](_0x497900(0x155)+_0x36ea44['message']);}}[a0_0x27e4e3(0x131)](_0x111f88){return new Promise(_0x1cf202=>setTimeout(_0x1cf202,_0x111f88));}}var F=$;export{F as default,$ as CommHub};
@@ -0,0 +1,211 @@
1
+ /** Per-node record, written into the node dir next to the other state files. */
2
+ export declare const CODEX_AUTH_FINGERPRINT_FILE = ".codex-auth-fingerprint.json";
3
+ /**
4
+ * Host-wide index of the same records — the read side's source of truth.
5
+ *
6
+ * Under `~/.anet/` because that is already this repo's host-scoped state
7
+ * directory (global config lives there) and it does not move with `cwd`, which
8
+ * is the entire point: the nodes that need to see each other are in different
9
+ * workspaces.
10
+ */
11
+ export declare function codexFingerprintIndexDir(home?: string): string;
12
+ /**
13
+ * Index filename for a node.
14
+ *
15
+ * 🔴 Derived from the node's DIRECTORY, never its alias. Aliases are not unique
16
+ * across workspaces — the reference fleet runs a node beside its own `2号`
17
+ * twin, and nothing stops two workspaces from using one name — so an
18
+ * alias-keyed file would let one node silently overwrite another's record,
19
+ * re-creating the very blindness this index fixes. A directory cannot be two
20
+ * nodes.
21
+ *
22
+ * 🔴 And derived from the directory rather than from `node_id`, even though the
23
+ * CLI has one handy: agent-node's `NODE_ID` can be empty (older configs), so
24
+ * a node_id key would need a fallback — and then the same node would write
25
+ * one filename from one launch path and a different one from the other,
26
+ * leaving two records that look like two nodes sharing a credential. One
27
+ * deterministic key from an input both call sites already have is worth more
28
+ * than a prettier name. `node_id` is still recorded, for humans.
29
+ */
30
+ export declare function codexFingerprintIndexFile(nodeDir: string): string;
31
+ /** Length of the stored fingerprint. Collisions at 8 hex are ~1 in 4 billion;
32
+ * a false "these two share a login" warning costs a second look, while the
33
+ * value staying short keeps it obviously non-reversible in logs. */
34
+ export declare const FINGERPRINT_LENGTH = 8;
35
+ /** Access tokens measured on the reference fleet: `exp - iat` was exactly this,
36
+ * on 29 of 29 samples, with no jitter. Used only to phrase "how long until the
37
+ * shared copy dies" when we have an `exp` but no `iat`. */
38
+ export declare const ACCESS_TOKEN_LIFETIME_SECONDS = 864000;
39
+ /** Past this, a published record's age is shown beside the alias. It does not
40
+ * suppress the warning: a node that has not started in a week still holds the
41
+ * shared credential. See the liveness note on `checkCodexCredentialSharing`. */
42
+ export declare const STALE_RECORD_NOTICE_MS: number;
43
+ export interface CodexAuthFingerprintRecord {
44
+ readonly schema_version: 1 | 2 | 3;
45
+ readonly alias: string;
46
+ /** sha256(refresh_token) truncated — never the token. */
47
+ readonly fingerprint: string;
48
+ readonly written_at: string;
49
+ /** v2: when this copy's ACCESS token expires, ISO-8601, or null if unreadable.
50
+ * A timestamp, not a credential. Two nodes holding one copied file share this
51
+ * instant exactly — which is how "they stop together" becomes observable. */
52
+ readonly access_expires_at?: string | null;
53
+ /** v2: the CODEX_HOME this record was read from. Distinguishes "two copies of
54
+ * one credential" from "two nodes pointed at one directory", which need
55
+ * different fixes. */
56
+ readonly codex_home?: string | null;
57
+ /** v3: the node directory this record describes, canonical. Three jobs: it is
58
+ * the identity used to de-duplicate the index against the sibling scan and to
59
+ * exclude self; and it is the liveness test — if this directory is gone, the
60
+ * node is gone and the record must not accuse anyone. */
61
+ readonly node_dir?: string;
62
+ /** v3: recorded for humans reading the index by hand. Never the key: it can be
63
+ * absent, and a key that is sometimes absent produces two records per node. */
64
+ readonly node_id?: string | null;
65
+ }
66
+ /**
67
+ * Hash the refresh token out of an auth.json body.
68
+ *
69
+ * Accepts both shapes seen in the wild: the current codex layout nests it
70
+ * under `tokens` (`{auth_mode, tokens:{id_token, access_token, refresh_token,
71
+ * account_id}, last_refresh}`), and older/plain bodies put `refresh_token` at
72
+ * the top level. Anything else — unparsable, absent, empty, non-string —
73
+ * returns null, because "we cannot tell" must not be reported as "no
74
+ * collision".
75
+ */
76
+ export declare function fingerprintRefreshToken(authJsonText: string): string | null;
77
+ /**
78
+ * When this copy's access token expires, read out of the JWT's own payload.
79
+ *
80
+ * The signature is NOT verified and nothing here authenticates: we are reading
81
+ * a timestamp the token states about itself, the same way `jwt.io` would. A
82
+ * token that is not a JWT, or carries no numeric `exp`, yields null — unknown
83
+ * stays unknown.
84
+ */
85
+ export declare function accessTokenExpiry(authJsonText: string): Date | null;
86
+ export interface NodeFingerprint {
87
+ readonly alias: string;
88
+ /** null when the node has no auth.json, or one we could not read. */
89
+ readonly fingerprint: string | null;
90
+ /** When the record was written; used to say how stale a claim is. */
91
+ readonly writtenAt?: string | null;
92
+ /** When this copy's access token expires, if we could read it. */
93
+ readonly accessExpiresAt?: Date | null;
94
+ /** The CODEX_HOME this fingerprint came from, if known. */
95
+ readonly codexHome?: string | null;
96
+ /** Canonical node directory — identity for de-duplication and self-exclusion. */
97
+ readonly nodeDir?: string | null;
98
+ }
99
+ /**
100
+ * Other nodes holding the same credential chain as `self`.
101
+ *
102
+ * Records with no fingerprint are skipped rather than grouped: "unknown" is
103
+ * not a match.
104
+ *
105
+ * 🔴 Self is excluded by node DIRECTORY when both sides carry one, and only
106
+ * falls back to alias for pre-v3 records. Once the read side is host-wide,
107
+ * alias stops being an identity: two workspaces may each hold a node called
108
+ * the same thing, and excluding by name would hide a genuine collision
109
+ * between them — the exact failure this index was added to fix.
110
+ */
111
+ export declare function collidingNodes(records: readonly NodeFingerprint[], self: NodeFingerprint): NodeFingerprint[];
112
+ /**
113
+ * The warning an operator sees at start. Returns [] when nothing collides —
114
+ * callers print exactly what they get, so silence is representable and the
115
+ * "no collision" path cannot accidentally print a scary empty banner.
116
+ *
117
+ * Deliberately a warning and never a refusal: every node on a host shares one
118
+ * login today, so refusing to start would take the whole box down at once
119
+ * over a condition that is survivable until the next refresh.
120
+ *
121
+ * 🔴 Two outcomes, and the wrong one is actively misleading. The default text
122
+ * ("whichever node refreshes first keeps working") assumes refresh WORKS.
123
+ * On a host that cannot reach the OAuth token endpoint — egress blocked, or
124
+ * a proxy that allowlists the model API and 403s everything else — nobody
125
+ * refreshes, and the nodes holding one copy do not degrade one at a time:
126
+ * they stop together the moment the shared access token expires. Field case:
127
+ * three nodes whose auth.json files were byte-identical, carrying one access
128
+ * token, all expired at the same instant.
129
+ *
130
+ * We do NOT probe the network to tell these apart — a start path is the wrong
131
+ * place to open a socket, and a probe would answer for this moment rather
132
+ * than for the window that matters. We branch on evidence already in the
133
+ * file: an access token whose `exp` has passed is a copy that demonstrably
134
+ * stopped being refreshed, which is the observable the field case exhibits.
135
+ * When `exp` is still in the future we cannot prove reachability either way,
136
+ * and the default wording is the right one to print.
137
+ */
138
+ export declare function sharedCredentialWarningLines(self: NodeFingerprint, colliding: readonly NodeFingerprint[], now?: Date): string[];
139
+ /**
140
+ * Two different things both read as "codex cannot refresh", and they need
141
+ * opposite remedies. Telling them apart is the whole value of this mapping:
142
+ * treating a transport failure as a rotation conflict sends an operator to
143
+ * copy someone else's auth.json, which is precisely how a shared-credential
144
+ * chain gets created.
145
+ */
146
+ export type CodexRefreshFailureKind =
147
+ /** Someone else spent this refresh token first. */
148
+ "rotation-conflict"
149
+ /** The token endpoint is unreachable — nobody's token is rotating. */
150
+ | "token-endpoint-unreachable";
151
+ export interface CodexRefreshFailure {
152
+ readonly kind: CodexRefreshFailureKind;
153
+ readonly lines: string[];
154
+ }
155
+ /**
156
+ * Name what actually went wrong with a codex refresh, and say what to do.
157
+ *
158
+ * Returns null for anything else, so callers fall through to whatever they
159
+ * printed before — an unrelated error must pass through unchanged.
160
+ *
161
+ * Order matters: a reuse rejection is a server answer and is checked first; a
162
+ * transport failure means no answer arrived at all.
163
+ */
164
+ export declare function describeCodexRefreshFailure(text: string, colliding?: readonly NodeFingerprint[]): CodexRefreshFailure | null;
165
+ export interface CodexCredentialSharingCheck {
166
+ /** This node's own directory — where its record is written. */
167
+ readonly nodeDir: string;
168
+ /** Shown to the operator; also how a node recognises its own record. */
169
+ readonly alias: string;
170
+ /** The CODEX_HOME whose auth.json this node will actually use. */
171
+ readonly codexHome: string;
172
+ /** Recorded for humans reading the index; never used as a key. Optional
173
+ * because agent-node's can be empty on older configs. */
174
+ readonly nodeId?: string | null;
175
+ /** Where the warning goes. Defaults to stderr. */
176
+ readonly say?: (message: string) => void;
177
+ /** Injected for tests; production passes nothing. */
178
+ readonly now?: Date;
179
+ /** Injected for tests; production uses the real host index under `~/.anet`. */
180
+ readonly indexDir?: string;
181
+ }
182
+ /**
183
+ * The whole operation: read this node's credential, publish an 8-hex record,
184
+ * read what the *other* nodes published, and warn if any of them is on the
185
+ * same chain. Returns the colliding nodes so a caller can name them again if
186
+ * codex later fails to refresh.
187
+ *
188
+ * 🔴 Reads the neighbours' published fingerprint files, never their
189
+ * credentials. A guard against credential sharing must not itself become a
190
+ * reason to open every node's auth.json.
191
+ *
192
+ * 🔴 Always recomputes. The fingerprint changes every time codex refreshes in
193
+ * place, so a stale record is a wrong answer; both call paths may run for
194
+ * one node in sequence, and whichever runs last must leave the current
195
+ * value, never an older one.
196
+ *
197
+ * 🔴 Liveness is EXISTENCE, not age. An index record outlives the node that
198
+ * wrote it, and a stale one accusing a node that no longer exists is worse
199
+ * than silence — it teaches operators to ignore the warning. So a record
200
+ * whose `node_dir` is gone is dropped and its index entry deleted.
201
+ * Age deliberately does NOT filter: on the reference fleet two of the three
202
+ * nodes in the worst-affected group were not running at all, and six of 29
203
+ * credential files had not been touched in days, while still holding the
204
+ * shared copy. An age cutoff would have hidden precisely the collisions
205
+ * worth reporting. Age is surfaced in the warning instead, so the operator
206
+ * can judge how old the claim is.
207
+ *
208
+ * Never throws and never refuses: observability must not be the reason a node
209
+ * will not start.
210
+ */
211
+ export declare function checkCodexCredentialSharing(opts: CodexCredentialSharingCheck): NodeFingerprint[];
@@ -0,0 +1,65 @@
1
+ export interface CodexHomeInheritedFile {
2
+ readonly name: string;
3
+ readonly mode: number;
4
+ /** Why a node needs it — printed when staged, so the action is legible. */
5
+ readonly because: string;
6
+ }
7
+ export declare const CODEX_HOME_INHERITED_FILES: readonly CodexHomeInheritedFile[];
8
+ export interface StatLike {
9
+ readonly mtimeMs: number;
10
+ }
11
+ export type StatFn = (path: string) => StatLike | null;
12
+ export interface CodexHomeStageStep {
13
+ readonly name: string;
14
+ readonly src: string;
15
+ readonly dst: string;
16
+ readonly mode: number;
17
+ readonly reason: "missing" | "host-newer";
18
+ readonly because: string;
19
+ }
20
+ /**
21
+ * What to copy from the host CODEX_HOME into the node's, right now.
22
+ *
23
+ * Pure: takes the stat function so the ordering rules are testable without a
24
+ * filesystem. A node file that is NEWER than the host's is left alone — codex
25
+ * refreshes its own copy in place, and clobbering it would throw away a fresher
26
+ * token than the one we hold.
27
+ */
28
+ export declare function codexHomeStagePlan(hostHome: string, nodeHome: string, stat: StatFn, join: (a: string, b: string) => string, files?: readonly CodexHomeInheritedFile[]): CodexHomeStageStep[];
29
+ export type CodexTuiBlocker = "sign-in" | "update-prompt" | "trust-prompt";
30
+ export type CodexTuiPaneState = CodexTuiBlocker | "not-painted" | "usable";
31
+ /**
32
+ * Classify the TUI, from two different reads of the same pane.
33
+ *
34
+ * They answer different questions and need different tmux flags — the same
35
+ * distinction `waitForTmuxPaneText` documents one screenful up:
36
+ *
37
+ * onScreen (capture-pane, no -S) → "is it sitting on a prompt right now"
38
+ * A prompt that was already answered stays in scrollback forever,
39
+ * so reading history here would report a fixed node as blocked.
40
+ *
41
+ * everSeen (capture-pane -S -N) → "did the TUI ever paint"
42
+ * The banner is printed once and scrolls away — an MCP error burst
43
+ * was enough to push it off screen in under a minute — so reading
44
+ * only the current screen here would report a working node as dead.
45
+ *
46
+ * 🔴 And "the pane has text" answers neither. An earlier version of this used
47
+ * "≥3 non-empty lines ⇒ ready" and passed a node parked on the sign-in page.
48
+ * Measured timeline for that start:
49
+ *
50
+ * t≈3s 22 non-empty lines ← launcher output, TUI not up yet
51
+ * t≈6s 0 non-empty lines ← codex clears the screen and takes over
52
+ * t≈9s 10 non-empty lines ← the sign-in page finally paints
53
+ *
54
+ * The rule fired at t≈3s, six seconds before the thing it was meant to catch
55
+ * existed.
56
+ */
57
+ export declare function codexTuiPaneState(onScreen: string, everSeen?: string): CodexTuiPaneState;
58
+ /**
59
+ * What the operator should read when a node came up but cannot work. Names the
60
+ * blocker AND where to look — a launcher that only says "not ready" sends
61
+ * someone hunting through three tmux sessions.
62
+ */
63
+ export declare function describeCodexTuiBlocker(blocker: CodexTuiBlocker, displayName: string, tuiSession: string): string;
64
+ /** The TUI never painted at all — a distinct failure from being blocked. */
65
+ export declare function describeCodexTuiNotPainted(displayName: string, tuiSession: string, waitedMs: number): string;