初始提交:terminalX 可运行态(M0/M1/M1.5 已真机验证)

- M0: libghostty SSH 终端(渲染/输入/连接)+ 白屏修复(OutputGate) + 会话状态机/自动重连
- M1: tsnet 用户态组网 + SSH-over-tsnet(fd 桥),shell 级真机验证;R5(Go+gvisor+C+++Swift 同进程) retire
- M1.5: tmux -CC 原生 tab(MVP)
- 结构: packages/(TXCore·TXTransport), apps/TerminalX, vendor/(libghostty-spm/libssh2/mbedtls/tsnet-bridge), artifacts/
- 文档: CLAUDE.md + docs/HANDOFF.md(新会话入口)
- 环境: 认证代理→依赖 vendor 本地化;Go 在 ~/.local/go;仅模拟器/未签名
- 待续: M2 mosh, tmux 多 pane, M4 安全(host key/SE)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
kid
2026-07-24 10:20:46 +08:00
commit aa92d0e676
2761 changed files with 803505 additions and 0 deletions

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>libCSSHCore.a</string>
<key>LibraryIdentifier</key>
<string>macos-arm64</string>
<key>LibraryPath</key>
<string>libCSSHCore.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>macos</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>libCSSHCore.a</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>libCSSHCore.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>libCSSHCore.a</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>libCSSHCore.a</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>

Binary file not shown.

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>AvailableLibraries</key>
<array>
<dict>
<key>BinaryPath</key>
<string>TsnetBridge.framework/TsnetBridge</string>
<key>LibraryIdentifier</key>
<string>ios-arm64</string>
<key>LibraryPath</key>
<string>TsnetBridge.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
</dict>
<dict>
<key>BinaryPath</key>
<string>TsnetBridge.framework/TsnetBridge</string>
<key>LibraryIdentifier</key>
<string>ios-arm64_x86_64-simulator</string>
<key>LibraryPath</key>
<string>TsnetBridge.framework</string>
<key>SupportedArchitectures</key>
<array>
<string>arm64</string>
<string>x86_64</string>
</array>
<key>SupportedPlatform</key>
<string>ios</string>
<key>SupportedPlatformVariant</key>
<string>simulator</string>
</dict>
</array>
<key>CFBundlePackageType</key>
<string>XFWK</string>
<key>XCFrameworkFormatVersion</key>
<string>1.0</string>
</dict>
</plist>

View File

@@ -0,0 +1,13 @@
// Objective-C API for talking to the following Go packages
//
// terminalx/tsnetbridge/tsnetbridge
//
// File is generated by gomobile bind. Do not edit.
#ifndef __TsnetBridge_FRAMEWORK_H__
#define __TsnetBridge_FRAMEWORK_H__
#include "Tsnetbridge.objc.h"
#include "Universe.objc.h"
#endif

View File

@@ -0,0 +1,59 @@
// Objective-C API for talking to terminalx/tsnetbridge/tsnetbridge Go package.
// gobind -lang=objc terminalx/tsnetbridge/tsnetbridge
//
// File is generated by gobind. Do not edit.
#ifndef __Tsnetbridge_H__
#define __Tsnetbridge_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@class TsnetbridgeNode;
/**
* Node 包装一个嵌入式 tsnet 节点。gomobile 导出为引用型对象。
*/
@interface TsnetbridgeNode : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
/**
* NewNode 创建(不启动)一个 tsnet 节点。stateDir 唯一、hostname 展示在管理台。
*/
- (nullable instancetype)init:(NSString* _Nullable)stateDir hostname:(NSString* _Nullable)hostname;
/**
* Close 释放节点。
*/
- (BOOL)close:(NSError* _Nullable* _Nullable)error;
/**
* DialTCPFD 经 tsnet 连接 tailnet 内 host:port返回一个已连接的 socket fd 供 libssh2 使用。
实现tsnet.Dial 得到 net.Connnetstack 虚拟连接,无真实 fd→ socketpair(AF_UNIX) →
两条 goroutine 双向 io.Copy 泵 → 把 socketpair 的另一端 fd 返回给 Swift。
Swift 侧 close(fd) 会触发泵结束并关闭 tsConn。返回 -1 + error 表示失败。
*/
- (BOOL)dialTCPFD:(NSString* _Nullable)hostOrIP port:(long)port timeoutMs:(long)timeoutMs ret0_:(int64_t* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
/**
* PeersJSON 返回 tailnet 内其它节点列表name/ip/online/os的 JSON用于选择连接目标。
*/
- (NSString* _Nonnull)peersJSON;
/**
* SelfIP 返回本节点的 Tailscale IPv4经 LocalClient().Status() 取;未就绪返回空串)。
*/
- (NSString* _Nonnull)selfIP;
/**
* UpWithAuthKey 用 auth key 启动并等待 RunningtimeoutMs 到则返回 error
gomobile 友好签名基本类型入参、error 出参。
*/
- (BOOL)upWithAuthKey:(NSString* _Nullable)authKey timeoutMs:(long)timeoutMs error:(NSError* _Nullable* _Nullable)error;
@end
/**
* NewNode 创建(不启动)一个 tsnet 节点。stateDir 唯一、hostname 展示在管理台。
*/
FOUNDATION_EXPORT TsnetbridgeNode* _Nullable TsnetbridgeNewNode(NSString* _Nullable stateDir, NSString* _Nullable hostname);
#endif

View File

@@ -0,0 +1,29 @@
// Objective-C API for talking to Go package.
// gobind -lang=objc
//
// File is generated by gobind. Do not edit.
#ifndef __Universe_H__
#define __Universe_H__
@import Foundation;
#include "ref.h"
@protocol Universeerror;
@class Universeerror;
@protocol Universeerror <NSObject>
- (NSString* _Nonnull)error;
@end
@class Universeerror;
@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (NSString* _Nonnull)error;
@end
#endif

View File

@@ -0,0 +1,35 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef __GO_REF_HDR__
#define __GO_REF_HDR__
#include <Foundation/Foundation.h>
// GoSeqRef is an object tagged with an integer for passing back and
// forth across the language boundary. A GoSeqRef may represent either
// an instance of a Go object, or an Objective-C object passed to Go.
// The explicit allocation of a GoSeqRef is used to pin a Go object
// when it is passed to Objective-C. The Go seq package maintains a
// reference to the Go object in a map keyed by the refnum along with
// a reference count. When the reference count reaches zero, the Go
// seq package will clear the corresponding entry in the map.
@interface GoSeqRef : NSObject {
}
@property(readonly) int32_t refnum;
@property(strong) id obj; // NULL when representing a Go object.
// new GoSeqRef object to proxy a Go object. The refnum must be
// provided from Go side.
- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
- (int32_t)incNum;
@end
@protocol goSeqRefInterface
-(GoSeqRef*) _ref;
@end
#endif

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>TsnetBridge</string>
<key>CFBundleIdentifier</key>
<string>TsnetBridge</string>
<key>MinimumOSVersion</key>
<string>100.0</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1784856790</string>
<key>CFBundleVersion</key>
<string>0.0.1784856790</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
framework module "TsnetBridge" {
header "ref.h"
header "Tsnetbridge.objc.h"
header "Universe.objc.h"
header "TsnetBridge.h"
export *
}

View File

@@ -0,0 +1,13 @@
// Objective-C API for talking to the following Go packages
//
// terminalx/tsnetbridge/tsnetbridge
//
// File is generated by gomobile bind. Do not edit.
#ifndef __TsnetBridge_FRAMEWORK_H__
#define __TsnetBridge_FRAMEWORK_H__
#include "Tsnetbridge.objc.h"
#include "Universe.objc.h"
#endif

View File

@@ -0,0 +1,59 @@
// Objective-C API for talking to terminalx/tsnetbridge/tsnetbridge Go package.
// gobind -lang=objc terminalx/tsnetbridge/tsnetbridge
//
// File is generated by gobind. Do not edit.
#ifndef __Tsnetbridge_H__
#define __Tsnetbridge_H__
@import Foundation;
#include "ref.h"
#include "Universe.objc.h"
@class TsnetbridgeNode;
/**
* Node 包装一个嵌入式 tsnet 节点。gomobile 导出为引用型对象。
*/
@interface TsnetbridgeNode : NSObject <goSeqRefInterface> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
/**
* NewNode 创建(不启动)一个 tsnet 节点。stateDir 唯一、hostname 展示在管理台。
*/
- (nullable instancetype)init:(NSString* _Nullable)stateDir hostname:(NSString* _Nullable)hostname;
/**
* Close 释放节点。
*/
- (BOOL)close:(NSError* _Nullable* _Nullable)error;
/**
* DialTCPFD 经 tsnet 连接 tailnet 内 host:port返回一个已连接的 socket fd 供 libssh2 使用。
实现tsnet.Dial 得到 net.Connnetstack 虚拟连接,无真实 fd→ socketpair(AF_UNIX) →
两条 goroutine 双向 io.Copy 泵 → 把 socketpair 的另一端 fd 返回给 Swift。
Swift 侧 close(fd) 会触发泵结束并关闭 tsConn。返回 -1 + error 表示失败。
*/
- (BOOL)dialTCPFD:(NSString* _Nullable)hostOrIP port:(long)port timeoutMs:(long)timeoutMs ret0_:(int64_t* _Nullable)ret0_ error:(NSError* _Nullable* _Nullable)error;
/**
* PeersJSON 返回 tailnet 内其它节点列表name/ip/online/os的 JSON用于选择连接目标。
*/
- (NSString* _Nonnull)peersJSON;
/**
* SelfIP 返回本节点的 Tailscale IPv4经 LocalClient().Status() 取;未就绪返回空串)。
*/
- (NSString* _Nonnull)selfIP;
/**
* UpWithAuthKey 用 auth key 启动并等待 RunningtimeoutMs 到则返回 error
gomobile 友好签名基本类型入参、error 出参。
*/
- (BOOL)upWithAuthKey:(NSString* _Nullable)authKey timeoutMs:(long)timeoutMs error:(NSError* _Nullable* _Nullable)error;
@end
/**
* NewNode 创建(不启动)一个 tsnet 节点。stateDir 唯一、hostname 展示在管理台。
*/
FOUNDATION_EXPORT TsnetbridgeNode* _Nullable TsnetbridgeNewNode(NSString* _Nullable stateDir, NSString* _Nullable hostname);
#endif

View File

@@ -0,0 +1,29 @@
// Objective-C API for talking to Go package.
// gobind -lang=objc
//
// File is generated by gobind. Do not edit.
#ifndef __Universe_H__
#define __Universe_H__
@import Foundation;
#include "ref.h"
@protocol Universeerror;
@class Universeerror;
@protocol Universeerror <NSObject>
- (NSString* _Nonnull)error;
@end
@class Universeerror;
@interface Universeerror : NSError <goSeqRefInterface, Universeerror> {
}
@property(strong, readonly) _Nonnull id _ref;
- (nonnull instancetype)initWithRef:(_Nonnull id)ref;
- (NSString* _Nonnull)error;
@end
#endif

View File

@@ -0,0 +1,35 @@
// Copyright 2015 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
#ifndef __GO_REF_HDR__
#define __GO_REF_HDR__
#include <Foundation/Foundation.h>
// GoSeqRef is an object tagged with an integer for passing back and
// forth across the language boundary. A GoSeqRef may represent either
// an instance of a Go object, or an Objective-C object passed to Go.
// The explicit allocation of a GoSeqRef is used to pin a Go object
// when it is passed to Objective-C. The Go seq package maintains a
// reference to the Go object in a map keyed by the refnum along with
// a reference count. When the reference count reaches zero, the Go
// seq package will clear the corresponding entry in the map.
@interface GoSeqRef : NSObject {
}
@property(readonly) int32_t refnum;
@property(strong) id obj; // NULL when representing a Go object.
// new GoSeqRef object to proxy a Go object. The refnum must be
// provided from Go side.
- (instancetype)initWithRefnum:(int32_t)refnum obj:(id)obj;
- (int32_t)incNum;
@end
@protocol goSeqRefInterface
-(GoSeqRef*) _ref;
@end
#endif

View File

@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>TsnetBridge</string>
<key>CFBundleIdentifier</key>
<string>TsnetBridge</string>
<key>MinimumOSVersion</key>
<string>100.0</string>
<key>CFBundleShortVersionString</key>
<string>0.0.1784856790</string>
<key>CFBundleVersion</key>
<string>0.0.1784856790</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
</dict>
</plist>

View File

@@ -0,0 +1,8 @@
framework module "TsnetBridge" {
header "ref.h"
header "Tsnetbridge.objc.h"
header "Universe.objc.h"
header "TsnetBridge.h"
export *
}