@syrkos/filaxis 0.1.0-alpha.10

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 (85) hide show
  1. package/AGENTS.md +46 -0
  2. package/LICENSE +202 -0
  3. package/NOTICE +10 -0
  4. package/README.md +61 -0
  5. package/bin/filaxis.ts +112 -0
  6. package/dist/agent-toolkit.d.ts +99 -0
  7. package/dist/dialect.d.ts +31 -0
  8. package/dist/driver.d.ts +130 -0
  9. package/dist/events.d.ts +26 -0
  10. package/dist/factory.d.ts +16 -0
  11. package/dist/file-edit.d.ts +43 -0
  12. package/dist/file-transfer.d.ts +44 -0
  13. package/dist/index.d.ts +38 -0
  14. package/dist/index.js +4200 -0
  15. package/dist/layer-discovery.d.ts +30 -0
  16. package/dist/layer-env.d.ts +95 -0
  17. package/dist/local-driver.d.ts +47 -0
  18. package/dist/local-session-manager.d.ts +98 -0
  19. package/dist/logger.d.ts +12 -0
  20. package/dist/remote-session-manager.d.ts +64 -0
  21. package/dist/runtime-stack.d.ts +52 -0
  22. package/dist/session-buffer.d.ts +73 -0
  23. package/dist/session-types.d.ts +74 -0
  24. package/dist/shell-discovery.d.ts +4 -0
  25. package/dist/ssh-helpers.d.ts +88 -0
  26. package/dist/ssh-pty-driver.d.ts +74 -0
  27. package/dist/stream-session-manager.d.ts +83 -0
  28. package/dist/stream-window.d.ts +124 -0
  29. package/dist/terminal/command-executer.d.ts +73 -0
  30. package/dist/terminal/output-buffer.d.ts +49 -0
  31. package/dist/terminal/session-launcher.d.ts +28 -0
  32. package/dist/terminal/session-registry.d.ts +29 -0
  33. package/dist/terminal/tmux-invoker.d.ts +8 -0
  34. package/dist/terminal/types.d.ts +56 -0
  35. package/dist/terminal-manager.d.ts +30 -0
  36. package/dist/tmux-driver.d.ts +49 -0
  37. package/dist/vt100-screen.d.ts +46 -0
  38. package/docs/DEVELOPMENT.md +38 -0
  39. package/docs/KNOWN-ISSUES.md +35 -0
  40. package/docs/implementation-notes.md +57 -0
  41. package/docs/skills/cross-host-diagnosis.md +21 -0
  42. package/docs/skills/file-sync.md +22 -0
  43. package/docs/skills/longrun-observe.md +20 -0
  44. package/docs/skills/stream-window.md +28 -0
  45. package/docs//345/256/214/346/225/264/345/267/241/346/243/200/346/212/245/345/221/212.md +141 -0
  46. package/docs//346/265/213/350/257/2252.md +112 -0
  47. package/docs//346/265/213/350/257/2253.md +73 -0
  48. package/docs//346/265/213/350/257/2254.md +138 -0
  49. package/docs//346/265/213/350/257/2255.md +124 -0
  50. package/docs//347/254/254/344/272/214/344/273/275/345/267/241/346/243/200/346/212/245/345/221/212.md +103 -0
  51. package/examples/agent-tools.ts +74 -0
  52. package/examples/cross-host-diagnosis.ts +49 -0
  53. package/examples/longrun-observe.ts +46 -0
  54. package/package.json +47 -0
  55. package/src/agent-toolkit.ts +247 -0
  56. package/src/dialect.ts +100 -0
  57. package/src/driver.ts +142 -0
  58. package/src/events.ts +96 -0
  59. package/src/factory.ts +51 -0
  60. package/src/file-edit.ts +195 -0
  61. package/src/file-transfer.ts +196 -0
  62. package/src/index.ts +38 -0
  63. package/src/layer-discovery.ts +79 -0
  64. package/src/layer-env.ts +331 -0
  65. package/src/local-driver.ts +325 -0
  66. package/src/local-session-manager.ts +397 -0
  67. package/src/logger.ts +19 -0
  68. package/src/remote-session-manager.ts +286 -0
  69. package/src/runtime-stack.ts +128 -0
  70. package/src/session-buffer.ts +183 -0
  71. package/src/session-types.ts +78 -0
  72. package/src/shell-discovery.ts +52 -0
  73. package/src/ssh-helpers.ts +225 -0
  74. package/src/ssh-pty-driver.ts +655 -0
  75. package/src/stream-session-manager.ts +296 -0
  76. package/src/stream-window.ts +309 -0
  77. package/src/terminal/command-executer.ts +374 -0
  78. package/src/terminal/output-buffer.ts +126 -0
  79. package/src/terminal/session-launcher.ts +146 -0
  80. package/src/terminal/session-registry.ts +98 -0
  81. package/src/terminal/tmux-invoker.ts +65 -0
  82. package/src/terminal/types.ts +85 -0
  83. package/src/terminal-manager.ts +83 -0
  84. package/src/tmux-driver.ts +167 -0
  85. package/src/vt100-screen.ts +166 -0
@@ -0,0 +1,30 @@
1
+ /**
2
+ * layer-discovery.ts — 异步层环境探测助手(冷启动锦囊之异步侧)
3
+ *
4
+ * 探测不阻塞建层:`discoverLayer(driver)` 返回 Promise,消费方(自发现编排/
5
+ * 观察窗)自行选择 fire-and-forget 或 await——建层与探测解耦。
6
+ * 两段式(stage1 快 / stage2 慢包导入)+ 蒸馏 + 落盘(stale 防漂移)+ 可选跳过 stage2。
7
+ */
8
+ import { LayerEnvStore, type LayerEnvEntry, type LayerEnvironmentSpec } from "./layer-env.js";
9
+ import type { RuntimeDriver } from "./driver.js";
10
+ export interface DiscoverLayerOptions {
11
+ /** 落盘 Store(缺省内存态——探测结果仍返回不落盘) */
12
+ store?: LayerEnvStore;
13
+ /** 跳过 stage2(慢包导入——10s+;快路径/离线探测) */
14
+ skipStage2?: boolean;
15
+ /** stage2 独立超时(缺省 120s——由调用方驱动 exec 超时) */
16
+ stage2TimeoutMs?: number;
17
+ logger?: {
18
+ warn(msg: string): void;
19
+ };
20
+ }
21
+ export interface DiscoverLayerResult {
22
+ key: string;
23
+ spec: LayerEnvironmentSpec;
24
+ /** stage2 失败/跳过时如实标注(诚实不假装完整) */
25
+ probeNote?: string;
26
+ stale?: boolean;
27
+ entry?: LayerEnvEntry;
28
+ }
29
+ /** 异步探测一层环境:两段式 → 蒸馏 → (可选)落盘(漂移标 stale 不覆盖) */
30
+ export declare function discoverLayer(driver: RuntimeDriver, opts?: DiscoverLayerOptions): Promise<DiscoverLayerResult>;
@@ -0,0 +1,95 @@
1
+ import type { RuntimeDescriptor } from "./driver.js";
2
+ import { type SshConnParams } from "./ssh-helpers.js";
3
+ /** 层环境规格(蒸馏快照——版本号/有无/型号,非全量 dump) */
4
+ export interface LayerEnvironmentSpec {
5
+ os?: string;
6
+ kernel_arch?: string;
7
+ python?: string;
8
+ node?: string;
9
+ bun?: string;
10
+ java?: string;
11
+ cuda?: string;
12
+ gpu?: {
13
+ model: string;
14
+ vram_mb?: number;
15
+ };
16
+ docker?: boolean;
17
+ /** 关键包(present-only,"torch@2.4.0" 形态;匹配按 @ 前名) */
18
+ packages?: string[];
19
+ }
20
+ export interface SshHopLite {
21
+ host: string;
22
+ conn?: SshConnParams;
23
+ }
24
+ /** 重进路径投影(agent 据此零试错重进该层;环境身份不含 hops,重进路径含) */
25
+ export interface LayerConnectionInfo {
26
+ driver: string;
27
+ target?: string;
28
+ conn?: SshConnParams;
29
+ hops?: SshHopLite[];
30
+ enters?: Array<{
31
+ cmd: string;
32
+ label?: string;
33
+ }>;
34
+ launch_cmd?: string;
35
+ }
36
+ /** 单层条目 */
37
+ export interface LayerEnvEntry {
38
+ connection: LayerConnectionInfo;
39
+ environment: LayerEnvironmentSpec;
40
+ discovered_at: string;
41
+ /** 连接拓扑+环境快照 hash(漂移检测锚点:命中不一致 → stale 供重探,不自动覆盖) */
42
+ fingerprint: string;
43
+ /** 探测部分失败的说明(诚实标注,不假装完整) */
44
+ probe_note?: string;
45
+ }
46
+ export interface LayerEnvConfigFile {
47
+ layers: Record<string, LayerEnvEntry>;
48
+ }
49
+ /**
50
+ * 环境身份键(两键两职责之一:driverKey 管连接复用,本键管规格归属):
51
+ * 落点[+端口]/enter 标签链——hops 不进键(同落点经不同路径=同一环境规格)。
52
+ */
53
+ export declare function layerEnvKey(desc: RuntimeDescriptor): string;
54
+ /** stage 1(快:亚秒级)——OS/架构/语言运行时/GPU/CUDA/docker;输出行 `fx_key=value` */
55
+ export declare function buildProbeStage1(): string;
56
+ /** stage 2(慢:python 冷导入 10s+)——关键包版本;有 GNU timeout 逐项 15s 兜底 */
57
+ export declare function buildProbeStage2(): string;
58
+ /** 关键包探测清单(扩展在此加行) */
59
+ export declare const PROBE_PACKAGES: Array<{
60
+ key: string;
61
+ kind: "python" | "tool";
62
+ probe: string;
63
+ matchNames: string[];
64
+ }>;
65
+ /**
66
+ * 探测输出解析(纯函数):`fx_key=value` 行 → 蒸馏规格。
67
+ * PTY 回显防御:回显行是未展开原文(值含 `$(`)——一律丢弃。
68
+ * 真实性红线:nvidia-smi 失败文案(驱动不通信)不得记为 GPU 型号。
69
+ */
70
+ export declare function parseProbeOutput(stdout: string): LayerEnvironmentSpec;
71
+ export declare class LayerEnvStore {
72
+ readonly path: string;
73
+ private cache;
74
+ constructor(path: string);
75
+ load(force?: boolean): Promise<LayerEnvConfigFile>;
76
+ /** 原子写:tmp + rename */
77
+ save(cfg: LayerEnvConfigFile): Promise<void>;
78
+ /** 写入/更新一层规格;漂移检测:指纹不一致标 stale 不自动覆盖(显式 force 才覆写) */
79
+ upsert(key: string, entry: LayerEnvEntry, force?: boolean): Promise<{
80
+ stale: boolean;
81
+ }>;
82
+ }
83
+ /** 连接投影(descriptor → LayerConnectionInfo;重进路径含 hops) */
84
+ export declare function projectConnection(desc: RuntimeDescriptor): LayerConnectionInfo;
85
+ /** 指纹:连接投影 + 环境快照 hash */
86
+ export declare function layerFingerprint(conn: LayerConnectionInfo, spec: LayerEnvironmentSpec): string;
87
+ export interface LayerMatchResult {
88
+ key: string;
89
+ entry: LayerEnvEntry;
90
+ }
91
+ /**
92
+ * 按需求匹配层:needs 形如 "gpu" / "torch"(包名) / "python>=3.12"(版本比较)。
93
+ * 全部 need 命中才入选;结果不排序(调用方按需排)。
94
+ */
95
+ export declare function matchLayers(cfg: LayerEnvConfigFile, needs: string[]): LayerMatchResult[];
@@ -0,0 +1,47 @@
1
+ import type { RuntimeDriver, FileSystemDriver, ExecOptions, ExecResult, RuntimeDescriptor } from "./driver.js";
2
+ import { LocalSessionManager } from "./local-session-manager.js";
3
+ import type { SessionStartOptions, SessionHandleInfo, WatchOptions, ReadLogOptions } from "./session-types.js";
4
+ import type { FilaxisLogger } from "./logger.js";
5
+ export interface LocalDriverOptions {
6
+ /** 缺省工作目录 */
7
+ cwd?: string;
8
+ /** exec 状态/日志目录(缺省 os.tmpdir()/filaxis-exec) */
9
+ execDir?: string;
10
+ /** 执行 shell(缺省 bash) */
11
+ shell?: string;
12
+ logger?: FilaxisLogger;
13
+ }
14
+ /** 本地 Transport:进程内执行 + 原生 fs */
15
+ export declare class LocalRuntimeDriver implements RuntimeDriver {
16
+ descriptor: RuntimeDescriptor;
17
+ fs: FileSystemDriver;
18
+ /** 会话式 exec 引擎(长跑 + 双文件落盘 + 热窗口 + watch) */
19
+ readonly sessions: LocalSessionManager;
20
+ private readonly defaultCwd?;
21
+ private readonly execDir;
22
+ private readonly shell;
23
+ private readonly log;
24
+ constructor(opts?: LocalDriverOptions);
25
+ /** 从 descriptor 构建(descriptor.cwd 初始化缺省工作目录) */
26
+ static fromDescriptor(descriptor: RuntimeDescriptor, fallbackCwd?: string): LocalRuntimeDriver;
27
+ init(): Promise<void>;
28
+ destroy(): Promise<void>;
29
+ getCwd(): Promise<string>;
30
+ getEnv(key: string): Promise<string | undefined>;
31
+ execSession(command: string, opts?: SessionStartOptions): Promise<SessionHandleInfo>;
32
+ tailSession(sessionId: string, lines?: number): Promise<string[]>;
33
+ readSessionLog(sessionId: string, opts?: ReadLogOptions): Promise<string>;
34
+ watchSession(sessionId: string, opts: WatchOptions): {
35
+ cancel(): void;
36
+ };
37
+ stopSession(sessionId: string): Promise<{
38
+ exitCode?: number | null;
39
+ }>;
40
+ listSessions(): Array<{
41
+ sessionId: string;
42
+ command: string;
43
+ running: boolean;
44
+ startedAt: number;
45
+ }>;
46
+ exec(command: string, options?: ExecOptions): Promise<ExecResult>;
47
+ }
@@ -0,0 +1,98 @@
1
+ /**
2
+ * local-session-manager.ts — 本地长跑会话引擎(spawn 即返 + 双文件落盘 + 热窗口 + watcher)
3
+ *
4
+ * 净室平移自 Aethelum-Nexus `src/core/tools/runtime/session/local-session-manager.ts`
5
+ * (源锚点:Aethelum-Nexus dev @ 8977ff3 + fix 203a31c),按 REQ-0001 OSS 化改造:
6
+ * - 剥 SubstrateSecurity(执行网/沙箱属消费方策略——内核不越权预设安全边界)
7
+ * - SessionNotifier 队列投递 → 纯 onEvent 回调(内核零队列红线)
8
+ * - 落盘协议改双文件 `<logBase>.out` / `<logBase>.err`(FEAT-04——源版单文件混写)
9
+ * - 热窗口行对象带 stream 标记;聚合序为到达序(REQ §3.2 跨流顺序契约)
10
+ * - logger 可注入(缺省 noop);日志目录/Shell 可配
11
+ *
12
+ * 终端语义:start 立即返回,进程长跑(无自动超时——长跑是特性)。
13
+ * 三级读取:文件全量(完整行落盘,1MB/行防爆 + 64MiB 总量硬顶)+ 热窗口 + watcher 推送。
14
+ * 生命周期:退出后句柄保留 ttlMs(默认 10min)供补读,TTL 后回收(timer unref 不撑进程)。
15
+ */
16
+ import { type ChildProcess } from "node:child_process";
17
+ import type { SessionStartOptions, SessionHandleInfo, SessionEvent, WatchOptions, ReadLogOptions } from "./session-types.js";
18
+ import { type FilaxisLogger } from "./logger.js";
19
+ export interface LocalSessionManagerOptions {
20
+ maxLines?: number;
21
+ maxLineBytes?: number;
22
+ /** 退出后句柄保留时长,默认 10min */
23
+ ttlMs?: number;
24
+ /** 会话日志目录(缺省 os.tmpdir()/filaxis-sessions) */
25
+ logDir?: string;
26
+ /** 执行 shell(缺省 "bash";Windows 需 Git Bash/WSL 提供 bash——平台差异显式声明,不静默切换) */
27
+ shell?: string;
28
+ /** spawn 注入(缺省 node:child_process.spawn)——消费方沙箱包装/测试 mock 注入点 */
29
+ spawnImpl?: (cmd: string, argv: string[], opts: {
30
+ env: NodeJS.ProcessEnv;
31
+ cwd?: string;
32
+ stdio: unknown[];
33
+ }) => ChildProcess;
34
+ /** 可注入日志(缺省 noop——SDK 不替调用方往 stdout 喷日志) */
35
+ logger?: FilaxisLogger;
36
+ }
37
+ export declare class LocalSessionManager {
38
+ /** 事件回调(FEAT-09:消费方订阅点;缺省 noop)。回调异常被吞并记日志,不杀会话 */
39
+ onEvent: (ev: SessionEvent) => void;
40
+ private readonly entries;
41
+ private readonly maxLines;
42
+ private readonly maxLineBytes;
43
+ private readonly ttlMs;
44
+ private readonly logDir;
45
+ private readonly shell;
46
+ private readonly log;
47
+ private readonly spawnImpl;
48
+ constructor(opts?: LocalSessionManagerOptions);
49
+ /** 启动长跑会话:立即返回句柄 */
50
+ start(command: string, opts?: SessionStartOptions): Promise<SessionHandleInfo>;
51
+ /** 热窗口快照(最近 n 行 text 投影,默认 50;不碰盘) */
52
+ tail(sessionId: string, n?: number): string[];
53
+ /** 热窗口行对象(带 stream 标记——按流过滤消费) */
54
+ tailLines(sessionId: string, n?: number): import("./session-buffer.js").SessionLine[];
55
+ /** 文件全量/大范围读取(窗口滚出的内容在这里;双文件按流分读) */
56
+ readLog(sessionId: string, opts?: ReadLogOptions): Promise<string>;
57
+ /**
58
+ * 注册 watcher:**回溯匹配**热窗口已有行(spawn→watch 注册间隙的输出不漏——
59
+ * 与 ready() 同款语义;真实反馈:bash 冷启热后 GO 常在注册前已进窗口),
60
+ * 未命中再匹配未来行;命中 → onEvent("match")。
61
+ */
62
+ watch(sessionId: string, opts: WatchOptions): {
63
+ cancel(): void;
64
+ };
65
+ /**
66
+ * 就绪握手(FEAT-11 / AC-13):先回溯扫描热窗口已有行(覆盖 spawn→ready
67
+ * 调用间隙已输出的标记——只监听增量则快输出进程必漏),未命中再监听增量行。
68
+ * 滚出感知有据:evictedCount===0 → 窗口历史完整,标记确定未出现,安心等待;
69
+ * >0 → 历史可能不完整,报「标记可能已滚出(可回查落盘日志)」而非死等。
70
+ * 超时 → 自动 stop 清理(不留孤儿进程)。
71
+ */
72
+ ready(sessionId: string, opts: {
73
+ pattern: string | RegExp;
74
+ timeoutMs: number;
75
+ }): Promise<{
76
+ matchedLine: string;
77
+ }>;
78
+ /**
79
+ * 停止会话:SIGTERM → 宽限 → SIGKILL 升级;随后短窗核实终态
80
+ * (FEAT-04:终止即请求、死亡须核实——close 事件到达=exited 带退出码;
81
+ * 核实窗内未死=stopped(SIGKILL 升级已安排),返回三态不静默当成功)
82
+ */
83
+ stop(sessionId: string): Promise<{
84
+ status: "exited" | "stopped" | "unknown";
85
+ exitCode?: number | null;
86
+ }>;
87
+ list(): Array<{
88
+ sessionId: string;
89
+ command: string;
90
+ running: boolean;
91
+ startedAt: number;
92
+ }>;
93
+ private require;
94
+ private ingestChunk;
95
+ private ingestLine;
96
+ private finalize;
97
+ private emit;
98
+ }
@@ -0,0 +1,12 @@
1
+ /**
2
+ * logger.ts — 可注入日志接口(REQ-0001 §8.1:内核不绑任何 logger 实现)
3
+ *
4
+ * 消费方注入自己的 logger;缺省 noop(静默内核——SDK 不替调用方往 stdout 喷日志)。
5
+ */
6
+ export interface FilaxisLogger {
7
+ debug(msg: string, ...args: unknown[]): void;
8
+ info(msg: string, ...args: unknown[]): void;
9
+ warn(msg: string, ...args: unknown[]): void;
10
+ error(msg: string, ...args: unknown[]): void;
11
+ }
12
+ export declare const noopLogger: FilaxisLogger;
@@ -0,0 +1,64 @@
1
+ import type { SessionStartOptions, SessionHandleInfo, SessionEvent, WatchOptions, ReadLogOptions, SessionFinalStatus } from "./session-types.js";
2
+ import type { ExecResult } from "./driver.js";
3
+ import { type FilaxisLogger } from "./logger.js";
4
+ export interface RemoteSessionManagerOptions {
5
+ /** 执行通道回调(远端命令落点) */
6
+ exec: (command: string) => Promise<Pick<ExecResult, "stdout" | "exitCode">>;
7
+ /** 远端会话日志目录(缺省 /tmp/filaxis-sessions) */
8
+ logDir?: string;
9
+ /** watcher 轮询间隔(默认 1500ms) */
10
+ pollMs?: number;
11
+ /** 无人消费且无 armed watcher 的回收 TTL(缺省 30min;时钟可注入测试) */
12
+ idleReapMs?: number;
13
+ logger?: FilaxisLogger;
14
+ }
15
+ export declare class RemoteSessionManager {
16
+ onEvent: (ev: SessionEvent) => void;
17
+ private entries;
18
+ private readonly exec;
19
+ private readonly logDir;
20
+ private readonly pollMs;
21
+ private readonly idleReapMs?;
22
+ private readonly log;
23
+ constructor(opts: RemoteSessionManagerOptions);
24
+ /** 启动远端长跑会话:nohup 双文件落盘 + 退出码文件;立即返回 */
25
+ start(command: string, opts?: SessionStartOptions): Promise<SessionHandleInfo>;
26
+ /** 热窗口快照(远端 tail .out) */
27
+ tail(sessionId: string, n?: number): Promise<string[]>;
28
+ /** 落盘日志读取(按流分读——FEAT-04 双文件) */
29
+ readLog(sessionId: string, opts?: ReadLogOptions): Promise<string>;
30
+ watch(sessionId: string, opts: WatchOptions): {
31
+ cancel(): void;
32
+ };
33
+ /**
34
+ * 行对象视图(双流:.out + .err 各取最近 n 行,行对象带 stream 标记)——
35
+ * observe 工具族用(第五季反馈 #2:此前仅 tail() 投影 stdout,stderr 漏读)
36
+ */
37
+ tailLines(sessionId: string, n?: number): Promise<Array<{
38
+ stream: "stdout" | "stderr";
39
+ text: string;
40
+ }>>;
41
+ /**
42
+ * 停止会话:发 kill -TERM → kill -0 核实。核实不可达(exec 抛错)→ 显式 unknown
43
+ * (终止即请求、死亡须核实——REQ §3.2 细则 6)。
44
+ */
45
+ stop(sessionId: string): Promise<{
46
+ status: SessionFinalStatus;
47
+ exitCode?: number | null;
48
+ }>;
49
+ list(): Array<{
50
+ sessionId: string;
51
+ command: string;
52
+ running: boolean;
53
+ startedAt: number;
54
+ }>;
55
+ /** 注意力衰减回收:无人消费且无 armed watcher 超 TTL → 自动收摊 + 事件广播(时钟可注入) */
56
+ reapIdle(now?: number, ttlMs?: number): void;
57
+ private require;
58
+ private startPolling;
59
+ /** 轮询:增量读 .out 喂 watcher;读 .code 判定终态 */
60
+ private poll;
61
+ private onLine;
62
+ private finalize;
63
+ private emit;
64
+ }
@@ -0,0 +1,52 @@
1
+ import type { RuntimeDriver, RuntimeDescriptor } from "./driver.js";
2
+ import { RuntimeFactory } from "./factory.js";
3
+ import { EventBus } from "./events.js";
4
+ import type { SessionEvent } from "./session-types.js";
5
+ import { type FilaxisLogger } from "./logger.js";
6
+ export type FilaxisEvents = SessionEvent | {
7
+ type: "layerState";
8
+ layer: string;
9
+ state: string;
10
+ };
11
+ export interface StackFeatures {
12
+ /** ControlMaster 多路复用可用(非 Windows + ssh 二进制存在) */
13
+ mux: boolean;
14
+ /** sftp 大文件快路径可用 */
15
+ sftp: boolean;
16
+ /** tmux 持久会话后端可用(缺席 → 持久层显式降级非持久) */
17
+ persistent: boolean;
18
+ /** 已注册 Transport 类型 */
19
+ transports: string[];
20
+ /** exec 通道 stderr 物理分离(平台默认;远端层的逐层标注属 driver 属性) */
21
+ stderrSeparated: boolean;
22
+ }
23
+ export interface RuntimeStackOptions {
24
+ logger?: FilaxisLogger;
25
+ factory?: RuntimeFactory;
26
+ }
27
+ export declare class RuntimeStack {
28
+ /** 进程级驱动缓存:同连接拓扑指纹复用既有连接(杜绝孤儿/重复建连) */
29
+ private static driverCache;
30
+ readonly events: EventBus<FilaxisEvents>;
31
+ private readonly factory;
32
+ private readonly log;
33
+ private featuresCache;
34
+ constructor(opts?: RuntimeStackOptions);
35
+ /**
36
+ * 连接拓扑指纹(净室移植自源版 driverKey,身份白名单投影):
37
+ * 显示标签/运行态缓存等非身份字段不进键——不把既有连接挤出缓存、不误建重复连接。
38
+ * 注:ssh 层的 enterSteps 管线属 ssh Transport 批次,届时并入 cfg 投影。
39
+ */
40
+ static driverKey(d: RuntimeDescriptor): string;
41
+ /** 建立层连接:指纹命中即复用(AC-07 连接计数语义) */
42
+ connect(descriptor: RuntimeDescriptor, fallbackCwd?: string): Promise<RuntimeDriver>;
43
+ /** 逐出缓存(销毁归调用方——先 evict 再 destroy,避免销毁竞态复用) */
44
+ static evictDriver(d: RuntimeDescriptor): RuntimeDriver | undefined;
45
+ /** 开放注册(透传 factory;AC-09 第三方 Transport 同权) */
46
+ registerDriver(type: string, f: (descriptor: RuntimeDescriptor) => RuntimeDriver): void;
47
+ /**
48
+ * 能力探测(AC-02:降级不靠猜)。结果缓存至注册表变化。
49
+ * Windows 无 ControlMaster → mux=false(自动退化直连为既定行为)。
50
+ */
51
+ features(): Promise<StackFeatures>;
52
+ }
@@ -0,0 +1,73 @@
1
+ /**
2
+ * session-buffer.ts — 会话窗口基础件(纯逻辑,无 I/O)
3
+ *
4
+ * 净室平移自 Aethelum-Nexus `src/core/tools/runtime/session/session-buffer.ts`
5
+ * (源锚点:Aethelum-Nexus dev @ 8977ff3)。
6
+ *
7
+ * LineAssembler 字节流按 \n 组行(CRLF 剥 \r;partial 暂存;flush 收尾)
8
+ * OutputRingBuffer 热窗口:maxLines × maxLineBytes 截断;截断仅发生在窗口副本
9
+ * ——落盘文件侧由调用方写完整行
10
+ * OSS 扩展(REQ-0001 FEAT-11):evictedCount 逐出计数——
11
+ * ready() 滚出感知「有据」的机制件(>0 = 窗口历史不完整)
12
+ * WatchRegistry 行级 watcher:string=子串 / RegExp 命中;once 默认;每会话上限
13
+ */
14
+ export declare class LineAssembler {
15
+ private pending;
16
+ /** 喂入一段输出,返回其中已成行的部分(不含尾部的 partial) */
17
+ feed(chunk: string): string[];
18
+ /** 进程退出时调用:无换行的残余强制成行 */
19
+ flush(): string[];
20
+ }
21
+ export interface RingBufferOptions {
22
+ maxLines?: number;
23
+ maxLineBytes?: number;
24
+ }
25
+ /** 输出流标记(定义于 session-types,此处 re-export 便利用户) */
26
+ export type { OutputStream } from "./session-types.js";
27
+ import type { OutputStream } from "./session-types.js";
28
+ /** 热窗口行对象:跨流聚合序为到达序(不承诺进程真实写入序——REQ §3.2) */
29
+ export interface SessionLine {
30
+ stream: OutputStream;
31
+ text: string;
32
+ }
33
+ export declare class OutputRingBuffer {
34
+ private readonly maxLines;
35
+ private readonly maxLineBytes;
36
+ private lines;
37
+ private evictedLines;
38
+ constructor(opts?: RingBufferOptions);
39
+ /** 完整行入窗(窗口侧按 maxLineBytes 硬截断 text 含标记;文件侧由调用方写原行) */
40
+ push(line: SessionLine): void;
41
+ /** 最近 n 行的 text 投影(简洁消费) */
42
+ tail(n: number): string[];
43
+ /** 最近 n 行对象(带 stream 标记——FEAT-05 按流过滤迭代用) */
44
+ tailLines(n: number): SessionLine[];
45
+ /**
46
+ * 自创建以来被挤出窗口的行数(FEAT-11 滚出感知有据):
47
+ * 0 = 窗口历史完整(标记若出现过必仍在窗内);>0 = 历史可能不完整。
48
+ */
49
+ get evictedCount(): number;
50
+ /**
51
+ * 命中行 ± contextLines 的上下文切片(索引相对当前窗口,越界收敛)。
52
+ * 供 watcher 命中时组装通知上下文。
53
+ */
54
+ contextAround(index: number, contextLines: number): SessionLine[];
55
+ /** 命中行的窗口索引(按 text 查找;找不到回退末行)——watch 上下文组装用 */
56
+ indexOfLine(text: string): number;
57
+ get size(): number;
58
+ }
59
+ export interface WatcherSpec {
60
+ id: string;
61
+ pattern: string | RegExp;
62
+ /** 命中一次即摘除(默认 true) */
63
+ once?: boolean;
64
+ }
65
+ export declare class WatchRegistry {
66
+ private watchers;
67
+ add(spec: WatcherSpec): void;
68
+ /** 匹配一行,返回命中的 watcher id(once 的命中即摘除) */
69
+ match(line: string): string[];
70
+ cancel(id: string): boolean;
71
+ get size(): number;
72
+ private toRegex;
73
+ }
@@ -0,0 +1,74 @@
1
+ /**
2
+ * session-types.ts — 会话生命周期公共类型
3
+ *
4
+ * 净室平移自 Aethelum-Nexus `src/core/tools/runtime/session/local-session-manager.ts`
5
+ * 类型段(源锚点:Aethelum-Nexus dev @ 8977ff3),按 REQ-0001 OSS 化裁剪:
6
+ * - 剔除 notifyQueue(通知路由目标队列——消息队列路由属消费方桥,内核零队列红线)
7
+ * - ownerSessionId 保留(纯透传的归属上下文 ID,无业务语义负载)
8
+ * - 新增终态三态 SessionFinalStatus(FEAT-04:终止即请求、死亡须核实)
9
+ */
10
+ export interface SessionStartOptions {
11
+ cwd?: string;
12
+ env?: Record<string, string>;
13
+ /** 会话名(sessionId 前缀,便于人读) */
14
+ name?: string;
15
+ /** 归属上下文 ID(事件通知时原样透传,供调用方关联自己的任务/请求) */
16
+ ownerSessionId?: string;
17
+ }
18
+ export interface SessionHandleInfo {
19
+ sessionId: string;
20
+ /** 落盘日志基名——实际双文件 `<logBase>.out` / `<logBase>.err`(FEAT-04 双文件协议) */
21
+ logBase: string;
22
+ pid?: number;
23
+ }
24
+ /**
25
+ * 会话终态三态(FEAT-04 / REQ §3.2 细则 6):
26
+ * - exited 收到进程退出码(自然退出或终止后的确认退出)
27
+ * - stopped 终止请求已发出且清理核实通过
28
+ * - unknown 核实不可达(SSH 断线/网络分区/核实超时)——显式暴露,严禁当成功
29
+ */
30
+ export type SessionFinalStatus = "exited" | "stopped" | "unknown";
31
+ export interface SessionFinalState {
32
+ status: SessionFinalStatus;
33
+ exitCode?: number;
34
+ }
35
+ export type SessionEvent = {
36
+ type: "match";
37
+ sessionId: string;
38
+ watcherId: string;
39
+ pattern: string;
40
+ matchedLine: string;
41
+ /** 命中行所属流(FEAT-04/05 双流标记) */
42
+ stream: "stdout" | "stderr";
43
+ context: string[];
44
+ /** 归属上下文(调用方透传) */
45
+ ownerSessionId?: string;
46
+ } | {
47
+ type: "exit";
48
+ sessionId: string;
49
+ exitCode: number | null;
50
+ lastLines: string[];
51
+ ownerSessionId?: string;
52
+ };
53
+ export interface WatchOptions {
54
+ pattern: string | RegExp;
55
+ /** 命中携带 命中行 ± N 行,默认 5 */
56
+ contextLines?: number;
57
+ /** 命中一次即摘除(默认 true) */
58
+ once?: boolean;
59
+ /**
60
+ * 命中即收摊:watcher 命中后自动 stop 会话——「观察对象结束 → 观察者退场」
61
+ * 从模型自觉变机制。观察型会话(tail -f 等永不退出的流)尤其需要,防遗忘泄漏。
62
+ */
63
+ thenStop?: boolean;
64
+ }
65
+ /** 输出流标记(FEAT-04/05:双流行对象——stdout/stderr 物理分离) */
66
+ export type OutputStream = "stdout" | "stderr";
67
+ export interface ReadLogOptions {
68
+ /** 取最近 N 行(缺省=全量) */
69
+ lines?: number;
70
+ /** 自文件头跳过 N 行 */
71
+ offsetLines?: number;
72
+ /** 读哪条流的落盘文件(FEAT-04 双文件协议;缺省 "stdout") */
73
+ stream?: OutputStream;
74
+ }
@@ -0,0 +1,4 @@
1
+ /** 发现本执行 shell(Linux/macOS 恒 "bash") */
2
+ export declare function resolveLocalShell(preferred?: string, log?: {
3
+ warn(msg: string): void;
4
+ }): string;
@@ -0,0 +1,88 @@
1
+ import type { RuntimeDescriptor } from "./driver.js";
2
+ /** 端口透传(随层连接生命周期——层在隧道在,层断即撤) */
3
+ export interface SshPortForward {
4
+ kind: "L" | "R" | "D";
5
+ port: number;
6
+ target?: string;
7
+ bind?: string;
8
+ }
9
+ export declare function renderForwardArg(f: SshPortForward): string;
10
+ /** SSH 连接参数(结构化——渲染进 ssh 命令行与身份解析) */
11
+ export interface SshConnParams {
12
+ user?: string;
13
+ port?: number;
14
+ keyFile?: string;
15
+ /** 跳板(-J;途径机不占栈层,由 ssh 自身代理) */
16
+ jump?: string;
17
+ forwards?: SshPortForward[];
18
+ /**
19
+ * 主机密钥策略(FEAT-12 / AC-12):
20
+ * - "tofu"(缺省)——accept-new:首连自动收主机键,已知主机不匹配则拒绝
21
+ * - "strict"——StrictHostKeyChecking=yes:仅已知主机可连(配合 knownHostsFile 自定义信任锚)
22
+ */
23
+ hostKeyPolicy?: "tofu" | "strict";
24
+ /** 自定义 known_hosts 路径(UserKnownHostsFile;strict 模式的信任锚,缺省用户默认) */
25
+ knownHostsFile?: string;
26
+ }
27
+ export type SshHop = string | {
28
+ host: string;
29
+ conn?: SshConnParams;
30
+ };
31
+ export declare function hopHost(hop: SshHop): string;
32
+ /** 人读形式:root@10.0.20.1:2222 -J jump -L8080→localhost:80 */
33
+ export declare function hopLabel(hop: SshHop): string;
34
+ /** ssh 命令行参数(spawn 数组与 ssh -G 解析共用) */
35
+ export declare function sshArgsFor(hop: SshHop): string[];
36
+ /** PTY 内单行发送所需的引用形式(私钥路径含空格等场景) */
37
+ export declare function sshArgsQuoted(hop: SshHop): string;
38
+ /** `~` 展开——spawn 参数数组不经过 shell,tilde 不会被展开(生产实证:公钥认证被拒 exit 255) */
39
+ export declare function expandHomePath(p: string): string;
40
+ /** 进入管线一步:建层时在链路末端落进内层 shell 的一条命令(docker exec / kubectl exec / su 等) */
41
+ export interface EnterStep {
42
+ /** 进入命令原文(重放用) */
43
+ cmd: string;
44
+ /** 显示/层选择标签(缺省截取 cmd) */
45
+ label?: string;
46
+ }
47
+ /** 层的完整进入管线(归一化读取):config.enterPipeline 为准;legacy enterCmd/enterLabel 就地归一 */
48
+ export declare function enterStepsOf(config: Record<string, unknown> | undefined): EnterStep[];
49
+ /**
50
+ * 自治建链选项(AC-12:host key 策略显式可配):
51
+ * - ConnectTimeout=10(先于握手超时暴露真相);ServerAlive 30×3(静默死亡 ~90s 内暴露)
52
+ * - hostKeyPolicy:tofu(缺省,accept-new)/ strict(yes + 可选 UserKnownHostsFile)
53
+ * 不加 BatchMode:禁交互提示会抹掉「等待输入」这个可感知状态——感知到 prompt 后
54
+ * 把原文直交调用方,而不是假装它不存在。
55
+ * 渲染只含密钥/known_hosts **路径**,永不包含其内容(AC-12 无泄漏红线)。
56
+ */
57
+ export declare function autonomousSshOpts(conn?: SshConnParams): string[];
58
+ /** root 层 spawn 全参数(含 -tt 强制 PTY) */
59
+ export declare function rootSshSpawnArgs(destArgs: string[], conn?: SshConnParams): string[];
60
+ /** PTY 内 hop 登录命令(选项语义与 root 对齐) */
61
+ export declare function hopSshCommand(hop: SshHop): string;
62
+ /** 「等待输入」感知特征:ssh 停在交互提示(密码/口令/yes-no)——检测到即失败交还原文 */
63
+ export declare const SSH_INPUT_WAIT_RE: RegExp;
64
+ /** 连接身份解析(ssh -G 本地解析不连网);失败回退 unresolved: 前缀(视为不相同,不误拦) */
65
+ export declare function resolveSshIdentity(hop: SshHop): Promise<string>;
66
+ /** 层的完整途经身份链(target + hops),供回环检测 */
67
+ export declare function layerPathIdentities(desc: RuntimeDescriptor): SshHop[];
68
+ /** 层显示名(root 含端口/用户 + 途经链 + 进入标签) */
69
+ export declare function layerDisplayName(desc: RuntimeDescriptor): string;
70
+ /** 层显示标签(descriptor 链 + 容器短 ID 后缀) */
71
+ export declare function layerDisplayLabel(d: {
72
+ descriptor: RuntimeDescriptor;
73
+ containerId?: string;
74
+ }): string;
75
+ export type ExecChannelRender = {
76
+ kind: "ok";
77
+ remoteArgs: string[];
78
+ stdinCmd: string;
79
+ } | {
80
+ kind: "unreachable";
81
+ reason: string;
82
+ step: string;
83
+ };
84
+ export declare function renderExecChannel(steps: EnterStep[], command: string, opts: {
85
+ cwd?: string;
86
+ marker: string;
87
+ nonceWrapped: string;
88
+ }): ExecChannelRender;