241 lines
12 KiB
TypeScript
241 lines
12 KiB
TypeScript
import type { Metadata } from "next";
|
|
import Link from "next/link";
|
|
import { PublicShell, StatusPill } from "./components/Shells";
|
|
import { getPublicCommercialSnapshot } from "@/db/repository";
|
|
import { getPublicBetaPresentation } from "@/db/domain";
|
|
|
|
export const dynamic = "force-dynamic";
|
|
|
|
export const metadata: Metadata = {
|
|
title: "把本地 coding-agent 接回手机",
|
|
description:
|
|
"NekoNest Cloud 让 Windows 与 Linux 主机主动出站连接,在手机上继续真实的本地 Codex、Claude Code、Kimi CLI 与 Grok Build 会话。",
|
|
};
|
|
|
|
export default async function Home() {
|
|
const commercial = await getPublicCommercialSnapshot();
|
|
const betaActive = Boolean(commercial.beta);
|
|
const publicBetaOpen = betaActive && commercial.blockedP0 === 0;
|
|
const betaCopy = getPublicBetaPresentation(betaActive);
|
|
|
|
return (
|
|
<PublicShell>
|
|
<section className="hero-section">
|
|
<div className="hero-grid">
|
|
<div className="hero-copy">
|
|
<div className="hero-kicker">
|
|
<StatusPill tone={publicBetaOpen ? "good" : betaActive ? "warn" : "neutral"}>
|
|
{publicBetaOpen ? betaCopy.status : betaActive ? "闭测免费 · 公开接入冻结" : betaCopy.status}
|
|
</StatusPill>
|
|
<span>{betaActive && !publicBetaOpen ? "免费政策已经预设;当前仅向明确受邀账户开放。" : betaCopy.subline}</span>
|
|
</div>
|
|
<h1>
|
|
把电脑上的
|
|
<br />
|
|
<em>coding-agent</em>
|
|
<br />
|
|
接回手机继续。
|
|
</h1>
|
|
<p className="hero-lead">
|
|
项目、CLI 凭据和原生会话留在你的 Windows 或 Linux 主机。NekoNest Cloud
|
|
负责托管可达性与中转,手机是你的安全遥控面。
|
|
</p>
|
|
<div className="hero-actions">
|
|
<Link className="button button-primary button-large" href="/dashboard">
|
|
{publicBetaOpen ? "连接自己的主机" : "进入控制台"}
|
|
<span aria-hidden="true">→</span>
|
|
</Link>
|
|
<Link className="button button-ghost button-large" href="/trust">
|
|
先看信任边界
|
|
</Link>
|
|
</div>
|
|
<div className="hero-facts" aria-label="产品关键事实">
|
|
<span><strong>0</strong> 家庭入站端口</span>
|
|
<span><strong>4</strong> 个现行 Agent</span>
|
|
<span><strong>{betaCopy.factValue}</strong> {betaCopy.factLabel}</span>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="hero-console" aria-label="移动控制台示意">
|
|
<div className="console-topbar">
|
|
<span className="console-dots" aria-hidden="true"><i /><i /><i /></span>
|
|
<span>我的乐园 / home-lab</span>
|
|
<StatusPill tone="good">主机在线</StatusPill>
|
|
</div>
|
|
<div className="console-layout">
|
|
<div className="console-tree">
|
|
<span className="tree-label">工作目录</span>
|
|
<strong>D:\work\nekonest</strong>
|
|
<div className="tree-agent active"><span>◎</span> Codex <small>全控制</small></div>
|
|
<div className="tree-thread active">继续商业化探索</div>
|
|
<div className="tree-thread">修复 daemon 重连</div>
|
|
<div className="tree-agent"><span>◌</span> Claude Code <small>兼容续聊</small></div>
|
|
<div className="tree-agent"><span>◌</span> Kimi CLI <small>兼容续聊</small></div>
|
|
</div>
|
|
<div className="console-chat">
|
|
<div className="chat-meta">
|
|
<span>Codex · 最后确认 21:48</span>
|
|
<StatusPill tone="info">已提交</StatusPill>
|
|
</div>
|
|
<div className="message assistant">
|
|
<span className="message-avatar">N</span>
|
|
<p>免费公测权益已经就绪。接下来验证真实主机配对与恢复流程。</p>
|
|
</div>
|
|
<div className="message user"><p>继续,把上线门禁也放进后台。</p></div>
|
|
<div className="delivery-row">
|
|
<span className="pulse-dot" />
|
|
业务确认来自主机,而不是把 WebSocket 写成功当成完成
|
|
</div>
|
|
<div className="composer-mock">
|
|
<span>从手机继续这个原生线程…</span>
|
|
<button type="button" aria-label="发送示意" disabled>↑</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div className="console-caption">界面示意,不代表 Cloud 运行了 Agent 或保存了原生会话正文。</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="proof-strip" aria-label="核心边界">
|
|
<span>主机主动出站</span>
|
|
<span>原生 store 为权威</span>
|
|
<span>目录 → Agent → 线程</span>
|
|
<span>Codex 全控制</span>
|
|
<span>自托管永久免费</span>
|
|
</section>
|
|
|
|
<section className="section light-section" id="how">
|
|
<div className="section-heading split-heading">
|
|
<div>
|
|
<span className="eyebrow">HOW IT WORKS / 连接方式</span>
|
|
<h2>Cloud 只站在该站的位置。</h2>
|
|
</div>
|
|
<p>
|
|
它不替你运行模型,不拿你的 API Key,也不浏览任意文件。守护进程从主机主动连出,手机沿着原生会话结构继续工作。
|
|
</p>
|
|
</div>
|
|
|
|
<div className="relay-diagram">
|
|
<div className="relay-node phone-node">
|
|
<span className="node-number">01</span>
|
|
<strong>手机 PWA</strong>
|
|
<small>浏览 · 发送 · 控制 · 通知</small>
|
|
</div>
|
|
<div className="relay-arrow"><span>HTTPS / WSS</span><i /></div>
|
|
<div className="relay-node cloud-node">
|
|
<span className="node-number">02</span>
|
|
<strong>NekoNest Cloud</strong>
|
|
<small>认证 · 路由 · 托管运维</small>
|
|
<b>不运行模型</b>
|
|
</div>
|
|
<div className="relay-arrow"><span>主机主动出站</span><i /></div>
|
|
<div className="relay-node host-node">
|
|
<span className="node-number">03</span>
|
|
<strong>你的主机</strong>
|
|
<small>Daemon · CLI · 原生 store · 项目</small>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="steps-grid">
|
|
<article><span>1</span><h3>安装主机守护进程</h3><p>Windows 与 Linux 正式支持。家里无需公网 IP,也不开放入站端口。</p></article>
|
|
<article><span>2</span><h3>一次性配对</h3><p>用短时配对码把主机接入自己的乐园。设备令牌独立、可撤销。</p></article>
|
|
<article><span>3</span><h3>继续原生线程</h3><p>按目录、Agent 和线程发现历史;能力做不到就明确说明,不给无效按钮。</p></article>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="section dark-section">
|
|
<div className="section-heading split-heading inverse">
|
|
<div>
|
|
<span className="eyebrow">BUILT FOR CONTINUATION</span>
|
|
<h2>不是又一个“问任何问题”的聊天站。</h2>
|
|
</div>
|
|
<p>它解决的是你离开电脑之后,真实的本地 agent 线程还要继续、解卡和完成。</p>
|
|
</div>
|
|
<div className="feature-ledger">
|
|
<article>
|
|
<span className="ledger-index">A</span>
|
|
<div><h3>投递状态说人话</h3><p>传输成功不等于 Agent 接受。待确认、已接受、已提交、失败和无法确定被分别呈现。</p></div>
|
|
</article>
|
|
<article>
|
|
<span className="ledger-index">B</span>
|
|
<div><h3>能力按 Agent 明示</h3><p>Codex 提供完整控制;Claude Code、Kimi CLI、Grok Build 按已探测能力兼容续聊。</p></div>
|
|
</article>
|
|
<article>
|
|
<span className="ledger-index">C</span>
|
|
<div><h3>本地仍是主场</h3><p>新线程只能落在 daemon 已发现的原生项目目录;没有永久 ghost thread,也不随意浏览磁盘。</p></div>
|
|
</article>
|
|
<article>
|
|
<span className="ledger-index">D</span>
|
|
<div><h3>公测状态不含糊</h3><p>免费政策、闭测邀请、容量限制和上线门禁分别记录,不靠积分、余额或未来收费承诺兜底。</p></div>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="section price-section">
|
|
<div className="price-callout">
|
|
<div className="price-copy">
|
|
<span className="eyebrow">FREE PUBLIC BETA</span>
|
|
<h2>前几个月,先免费把产品跑通。</h2>
|
|
<p>{publicBetaOpen ? "当前面向国内个人用户免费测试。无需支付方式,不生成报价或订单,也不会在结束时自动扣款。" : betaActive ? "免费测试政策已经预设,但公开接入仍由 P0 安全门禁冻结;受邀闭测账户免费,不需要支付方式。" : "免费公测政策已经结束,但收费功能仍未开放;后续决定会另行通知。"}</p>
|
|
<ul className="check-list">
|
|
<li>自托管版本永久免费</li>
|
|
<li>没有积分、钱包或 Token 充值</li>
|
|
<li>收费时机、方式和价格以后再定</li>
|
|
</ul>
|
|
</div>
|
|
<div className="price-board">
|
|
<div className="beta-price-row"><span>{betaCopy.priceHeading}</span><strong>{betaCopy.priceValue}</strong><small>{betaCopy.priceDetail}</small></div>
|
|
<div className="catalog-price-row">
|
|
<span>报价与订单</span>
|
|
<strong>未开放</strong>
|
|
<small>公测结束也不会自动创建</small>
|
|
</div>
|
|
<div className="catalog-price-row">
|
|
<span>未来收费方案</span>
|
|
<strong>以后再定</strong>
|
|
<small>以真实使用和成本数据为依据</small>
|
|
</div>
|
|
<Link href="/pricing">查看免费公测规则 →</Link>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="section trust-section">
|
|
<div className="trust-grid">
|
|
<div className="trust-title">
|
|
<span className="eyebrow">TRUST IS A BOUNDARY</span>
|
|
<h2>把能看见什么,写在产品正面。</h2>
|
|
<p>密封传输是 Cloud 的目标门槛,但当前附件链路还没有完成生产级端到端实证。因此我们不会提前写“零知识”。</p>
|
|
<Link className="text-link" href="/trust">查看可见性与风险边界 →</Link>
|
|
</div>
|
|
<div className="visibility-table" role="table" aria-label="数据可见性边界">
|
|
<div role="row" className="visibility-head"><span>数据</span><span>主机</span><span>Cloud 控制面</span></div>
|
|
<div role="row"><span>项目文件 / CLI 凭据</span><strong>保留</strong><em>不需要</em></div>
|
|
<div role="row"><span>原生会话库</span><strong>权威来源</strong><em>不取代</em></div>
|
|
<div role="row"><span>账号 / 主机 / 路由状态</span><strong>参与</strong><em>需要</em></div>
|
|
<div role="row"><span>提示词 / 回复 / 附件明文</span><strong>处理</strong><em>目标是不需要*</em></div>
|
|
<small>* 需以真实 sealed 命令与附件测试报告为准。</small>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section className="readiness-banner">
|
|
<div>
|
|
<StatusPill tone={commercial.blockedP0 ? "danger" : "good"}>{commercial.blockedP0 ? "免费公测尚未开放" : "公测门禁已通过"}</StatusPill>
|
|
<h2>{commercial.blockedP0 ? "控制台能跑,不等于托管链路已经可用。" : "免费公测已经具备基础开放条件。"}</h2>
|
|
<p>
|
|
{commercial.blockedP0
|
|
? `当前还有 ${commercial.blockedP0} 项免费公测 P0 门禁未通过,包括密封传输、租户隔离、主机认领、主体/域名路径和隐私保存。`
|
|
: "P0 证据已经齐全;仍需按邀请范围和运营容量逐步开放。"}
|
|
</p>
|
|
</div>
|
|
<Link className="button button-light button-large" href="/readiness">
|
|
打开上线检查表
|
|
<span aria-hidden="true">→</span>
|
|
</Link>
|
|
</section>
|
|
</PublicShell>
|
|
);
|
|
}
|