@syrkos/filaxis 0.1.0-alpha.11 → 0.1.0-alpha.13
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.
Potentially problematic release.
This version of @syrkos/filaxis might be problematic. Click here for more details.
- package/bin/filaxis.ts +91 -6
- package/dist/agent-toolkit.d.ts +46 -5
- package/dist/file-edit.d.ts +14 -6
- package/dist/index.js +322 -43
- package/dist/runtime-stack.d.ts +83 -1
- package/docs//346/265/213/350/257/2257.md +179 -0
- package/package.json +1 -1
- package/src/agent-toolkit.ts +143 -18
- package/src/file-edit.ts +33 -48
- package/src/runtime-stack.ts +290 -2
- package/src/ssh-pty-driver.ts +7 -4
package/bin/filaxis.ts
CHANGED
|
@@ -8,6 +8,11 @@
|
|
|
8
8
|
* edit 免 Shell 通道(第八季盲测实锤:Windows CommandLineToArgvW 剥引号、多行
|
|
9
9
|
* argv 要数缩进空格——Flash 卡 32 轮):--stdin-json / --request-file 走 JSON
|
|
10
10
|
* 载荷 {old,new,all},多行/引号/缩进 100% 保真,绕开宿主 Shell 转义。
|
|
11
|
+
*
|
|
12
|
+
* 路径描述对齐内核三件套(第九季盲测:CLI 只有 --host 族,跳板+容器场景 Agent
|
|
13
|
+
* 被迫读 19 轮源码写 6 个 TS 脚本):connParams(--jump/-J/--forward/--host-key/
|
|
14
|
+
* --known-hosts)+ sshHops 逐跳链(--hop 可重复)+ enterPipeline(--enter 可重复
|
|
15
|
+
* + --docker 糖)。每跳独立密钥等极端拓扑走 SDK descriptor 全量描述。
|
|
11
16
|
*/
|
|
12
17
|
import { RuntimeStack, LocalRuntimeDriver, SshPtyDriver, editFile, discoverLayer } from "../src/index.js";
|
|
13
18
|
import type { RuntimeDriver } from "../src/driver.js";
|
|
@@ -21,11 +26,14 @@ type MaybeAsync<T> = T | Promise<T>;
|
|
|
21
26
|
|
|
22
27
|
function parseOpts(argv: string[]): {
|
|
23
28
|
host?: string; user?: string; port?: number; key?: string;
|
|
29
|
+
jump?: string; hop: string[]; enter: string[];
|
|
30
|
+
docker?: string; dockerShell?: string; dockerRuntime?: string;
|
|
31
|
+
forward: string[]; hostKey?: string; knownHosts?: string;
|
|
24
32
|
timeout?: number; duration?: number; stream?: string; all?: boolean;
|
|
25
33
|
stdinJson?: boolean; requestFile?: string;
|
|
26
34
|
positional: string[];
|
|
27
35
|
} {
|
|
28
|
-
const o: ReturnType<typeof parseOpts> = { positional: [] };
|
|
36
|
+
const o: ReturnType<typeof parseOpts> = { positional: [], hop: [], enter: [], forward: [] };
|
|
29
37
|
for (let i = 0; i < argv.length; i++) {
|
|
30
38
|
const a = argv[i]!;
|
|
31
39
|
if (a === "--") continue; // 命令分隔符(可省)
|
|
@@ -34,6 +42,15 @@ function parseOpts(argv: string[]): {
|
|
|
34
42
|
case "--user": o.user = argv[++i]; break;
|
|
35
43
|
case "--port": o.port = parseInt(argv[++i]!, 10); break;
|
|
36
44
|
case "--key": o.key = argv[++i]; break;
|
|
45
|
+
case "-J": case "--jump": o.jump = argv[++i]; break;
|
|
46
|
+
case "--hop": o.hop.push(argv[++i]!); break;
|
|
47
|
+
case "--enter": o.enter.push(argv[++i]!); break;
|
|
48
|
+
case "--docker": o.docker = argv[++i]; break;
|
|
49
|
+
case "--docker-shell": o.dockerShell = argv[++i]; break;
|
|
50
|
+
case "--docker-runtime": o.dockerRuntime = argv[++i]; break;
|
|
51
|
+
case "--forward": o.forward.push(argv[++i]!); break;
|
|
52
|
+
case "--host-key": o.hostKey = argv[++i]; break;
|
|
53
|
+
case "--known-hosts": o.knownHosts = argv[++i]; break;
|
|
37
54
|
case "--timeout": o.timeout = parseInt(argv[++i]!, 10); break;
|
|
38
55
|
case "--duration": o.duration = parseInt(argv[++i]!, 10); break;
|
|
39
56
|
case "--stream": o.stream = argv[++i]; break;
|
|
@@ -46,12 +63,71 @@ function parseOpts(argv: string[]): {
|
|
|
46
63
|
return o;
|
|
47
64
|
}
|
|
48
65
|
|
|
66
|
+
/** 跳描述解析:user@host[:port](任一存在→结构化跳;纯 host→纯字符串跳,旧形态逐字节不变) */
|
|
67
|
+
function parseHopSpec(spec: string): { host: string; conn?: { user?: string; port?: number } } {
|
|
68
|
+
let rest = spec;
|
|
69
|
+
let user: string | undefined;
|
|
70
|
+
const at = rest.lastIndexOf("@");
|
|
71
|
+
if (at > 0) { user = rest.slice(0, at); rest = rest.slice(at + 1); }
|
|
72
|
+
let port: number | undefined;
|
|
73
|
+
const colon = rest.lastIndexOf(":");
|
|
74
|
+
if (colon > 0) {
|
|
75
|
+
const p = parseInt(rest.slice(colon + 1), 10);
|
|
76
|
+
if (Number.isFinite(p) && p > 0 && p < 65536) { port = p; rest = rest.slice(0, colon); }
|
|
77
|
+
}
|
|
78
|
+
return user != null || port != null ? { host: rest, conn: { user, port } } : { host: rest };
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** 端口透传解析:L:8080:localhost:80 / R:... / D:1080(bind 走 SDK descriptor) */
|
|
82
|
+
function parseForwardSpec(spec: string): { kind: "L" | "R" | "D"; port: number; target?: string } {
|
|
83
|
+
const parts = spec.split(":");
|
|
84
|
+
const kind = (parts[0] ?? "").toUpperCase();
|
|
85
|
+
if (!["L", "R", "D"].includes(kind)) throw new Error(`--forward 格式非法: '${spec}'(应为 L:port:host:port / R:... / D:port)`);
|
|
86
|
+
const port = parseInt(parts[1] ?? "", 10);
|
|
87
|
+
if (!Number.isInteger(port) || port <= 0 || port > 65535) throw new Error(`--forward 端口非法: '${spec}'`);
|
|
88
|
+
const target = kind === "D" ? undefined : parts.slice(2).join(":");
|
|
89
|
+
if (kind !== "D" && !target) throw new Error(`--forward kind=${kind} 需 target(host:port): '${spec}'`);
|
|
90
|
+
return { kind: kind as "L" | "R" | "D", port, target };
|
|
91
|
+
}
|
|
92
|
+
|
|
49
93
|
async function driverFor(opts: ReturnType<typeof parseOpts>): Promise<RuntimeDriver> {
|
|
50
94
|
if (opts.host) {
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
95
|
+
// ① connParams(root 连接参数——对齐内核 SshConnParams 全字段)
|
|
96
|
+
const connParams: Record<string, unknown> = {};
|
|
97
|
+
if (opts.user) connParams.user = opts.user;
|
|
98
|
+
if (opts.port != null) connParams.port = opts.port;
|
|
99
|
+
if (opts.key) connParams.keyFile = opts.key;
|
|
100
|
+
if (opts.jump) connParams.jump = opts.jump; // -J:途径机不占层,ssh 自身代理
|
|
101
|
+
if (opts.forward.length) connParams.forwards = opts.forward.map(parseForwardSpec);
|
|
102
|
+
if (opts.hostKey) {
|
|
103
|
+
if (opts.hostKey !== "tofu" && opts.hostKey !== "strict") {
|
|
104
|
+
throw new Error(`--host-key 取值非法: '${opts.hostKey}'(限 tofu | strict)`);
|
|
105
|
+
}
|
|
106
|
+
connParams.hostKeyPolicy = opts.hostKey;
|
|
107
|
+
}
|
|
108
|
+
if (opts.knownHosts) connParams.knownHostsFile = opts.knownHosts;
|
|
109
|
+
const config: Record<string, unknown> = {};
|
|
110
|
+
if (Object.keys(connParams).length) config.connParams = connParams;
|
|
111
|
+
// ② sshHops 逐跳链(每跳 user@host[:port],顺序=链序;密钥共享 --key——
|
|
112
|
+
// 每跳独立密钥等极端拓扑走 SDK descriptor)
|
|
113
|
+
if (opts.hop.length) config.sshHops = opts.hop.map(parseHopSpec);
|
|
114
|
+
// ③ enterPipeline 有序进入管线(--docker 糖在前 + --enter 按序追加;label
|
|
115
|
+
// 截取 cmd 前 30 字符=原版 push_enter 默认同款)
|
|
116
|
+
const enterSteps: Array<{ cmd: string; label: string }> = [];
|
|
117
|
+
if (opts.docker) {
|
|
118
|
+
const runtime = opts.dockerRuntime ?? "docker";
|
|
119
|
+
enterSteps.push({
|
|
120
|
+
cmd: `${runtime} exec -i ${opts.docker} ${opts.dockerShell ?? "sh"}`,
|
|
121
|
+
label: `${runtime}:${opts.docker}`,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
for (const e of opts.enter) enterSteps.push({ cmd: e, label: e.slice(0, 30) });
|
|
125
|
+
if (enterSteps.length) config.enterPipeline = enterSteps;
|
|
126
|
+
return new SshPtyDriver({ driver: "ssh", target: opts.host, config });
|
|
127
|
+
}
|
|
128
|
+
// local 层无路径概念——路径参数在场而 --host 缺席 = 防呆报错(静默忽略=错机器风险)
|
|
129
|
+
if (opts.jump || opts.hop.length || opts.enter.length || opts.docker || opts.forward.length || opts.hostKey || opts.knownHosts) {
|
|
130
|
+
throw new Error("路径描述参数(--jump/--hop/--enter/--docker/--forward/--host-key/--known-hosts)需要 --host(local 层无路径概念)");
|
|
55
131
|
}
|
|
56
132
|
return new LocalRuntimeDriver();
|
|
57
133
|
}
|
|
@@ -154,7 +230,16 @@ async function main() {
|
|
|
154
230
|
<path> --stdin-json | --request-file <f> # 免 Shell 通道(JSON {old,new,all}——多行/引号保真)
|
|
155
231
|
filaxis observe [--host ...] [--stream stderr|stdout|both] [--duration MS] -- <command>
|
|
156
232
|
filaxis probe [--host ...] # 两段式环境探测
|
|
157
|
-
|
|
233
|
+
|
|
234
|
+
路径描述(需 --host;对齐内核三件套 connParams/sshHops/enterPipeline):
|
|
235
|
+
-J, --jump <j> 跳板(-J:途径机不占层,ssh 自身代理)
|
|
236
|
+
--hop <user@host[:port]> 逐跳登录链(可重复=链序;每跳独立端口/用户,密钥共享 --key)
|
|
237
|
+
--enter <cmd> 进入内层 shell(可重复=管线序,如 "docker exec -i web bash")
|
|
238
|
+
--docker <name> 糖 = --enter "docker exec -i <name> sh"(--docker-shell bash / --docker-runtime podman 可换)
|
|
239
|
+
--forward L:8080:host:80 端口透传(可重复;R:/D: 同构;bind 走 SDK descriptor)
|
|
240
|
+
--host-key tofu|strict 主机密钥策略(缺省 tofu=accept-new)
|
|
241
|
+
--known-hosts <file> 自定义 known_hosts
|
|
242
|
+
每跳独立密钥等极端拓扑请用 SDK descriptor 全量描述。缺省 --host 为 local。`);
|
|
158
243
|
process.exit(cmd ? 1 : 0);
|
|
159
244
|
}
|
|
160
245
|
} finally {
|
package/dist/agent-toolkit.d.ts
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* agent-toolkit.ts — 原生 Agent 工具集(Gemini 试用反馈 #3
|
|
2
|
+
* agent-toolkit.ts — 原生 Agent 工具集(Gemini 试用反馈 #3 + 第十季层族)
|
|
3
3
|
*
|
|
4
|
-
* 一行 `createAgentToolkit(stack)` 生成 LLM
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
4
|
+
* 一行 `createAgentToolkit(stack)` 生成 LLM 工具面——OpenAI/Anthropic/Vercel AI SDK
|
|
5
|
+
* 通吃的 {tools, handlers} 双层结构:定义层喂模型,执行层留宿主(桥到任意框架)。
|
|
6
|
+
* 语义契约(退出码是数据/终态三态/就绪握手)由内核承载,宿主零胶水。
|
|
7
|
+
*
|
|
8
|
+
* 第十季层族:执行类工具带可选 layer 参数(缺省=默认层——最近 push 的命名层;
|
|
9
|
+
* 未用层族时与旧行为一致,零破坏);push_ssh/push_into/list_layers/remove_layer
|
|
10
|
+
* 操作 RuntimeStack 命名层注册表(Paramiko 式句柄寻址——栈/焦点弱化归消费方)。
|
|
8
11
|
*/
|
|
9
12
|
import type { RuntimeStack } from "./runtime-stack.js";
|
|
10
13
|
import type { RuntimeDriver } from "./driver.js";
|
|
@@ -53,6 +56,7 @@ export interface AgentToolHandlers {
|
|
|
53
56
|
duration_ms?: number;
|
|
54
57
|
stream?: "stdout" | "stderr" | "both";
|
|
55
58
|
name?: string;
|
|
59
|
+
layer?: string;
|
|
56
60
|
}): Promise<{
|
|
57
61
|
session_id: string;
|
|
58
62
|
lines: Array<{
|
|
@@ -65,6 +69,7 @@ export interface AgentToolHandlers {
|
|
|
65
69
|
ready_marker?: string;
|
|
66
70
|
error_pattern?: string;
|
|
67
71
|
name?: string;
|
|
72
|
+
layer?: string;
|
|
68
73
|
}): Promise<{
|
|
69
74
|
session_id: string;
|
|
70
75
|
log_base: string;
|
|
@@ -77,6 +82,42 @@ export interface AgentToolHandlers {
|
|
|
77
82
|
exit_code?: number | null;
|
|
78
83
|
note?: string;
|
|
79
84
|
}>;
|
|
85
|
+
push_ssh(args: {
|
|
86
|
+
host: string;
|
|
87
|
+
port?: number;
|
|
88
|
+
user?: string;
|
|
89
|
+
key?: string;
|
|
90
|
+
jump?: string;
|
|
91
|
+
name?: string;
|
|
92
|
+
}): Promise<{
|
|
93
|
+
layer: string;
|
|
94
|
+
reused: boolean;
|
|
95
|
+
reused_from?: string;
|
|
96
|
+
note?: string;
|
|
97
|
+
}>;
|
|
98
|
+
push_into(args: {
|
|
99
|
+
enter_cmd: string;
|
|
100
|
+
label?: string;
|
|
101
|
+
from?: string;
|
|
102
|
+
name?: string;
|
|
103
|
+
}): Promise<{
|
|
104
|
+
layer: string;
|
|
105
|
+
target?: string;
|
|
106
|
+
}>;
|
|
107
|
+
list_layers(args: Record<string, never>): Promise<{
|
|
108
|
+
text: string;
|
|
109
|
+
layers: Array<{
|
|
110
|
+
name: string;
|
|
111
|
+
driver: string;
|
|
112
|
+
target?: string;
|
|
113
|
+
}>;
|
|
114
|
+
}>;
|
|
115
|
+
remove_layer(args: {
|
|
116
|
+
name: string;
|
|
117
|
+
destroy?: boolean;
|
|
118
|
+
}): Promise<{
|
|
119
|
+
removed: string;
|
|
120
|
+
}>;
|
|
80
121
|
}
|
|
81
122
|
export interface AgentToolkit {
|
|
82
123
|
tools: AgentToolDef[];
|
package/dist/file-edit.d.ts
CHANGED
|
@@ -6,10 +6,16 @@
|
|
|
6
6
|
*
|
|
7
7
|
* 第七季盲测反馈(B2 逐秒拆解):旧实现一次 editFile = 5 次串行 SSH 往返
|
|
8
8
|
* (stat/read/stat/write/stat),Windows 无 ControlMaster 下放大到 15s+。
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* 第七季版合成「读+戳 1 次 + 远端 CAS 原子写回 1 次」——但方言探测(base64
|
|
10
|
+
* -w 0/-d/-D)是独立往返,SDK 常驻内存下有 dialectCache 掩护,**CLI 每次冷启动
|
|
11
|
+
* 实为 3 次物理往返**(第十季 B5 轨迹实锤:3×SSH 握手 ≈11.4s 突破宿主 10s 后台
|
|
12
|
+
* 阈值,多耗 3 轮轮询)。
|
|
13
|
+
*
|
|
14
|
+
* 本版(第十季):**真 2 次往返**——方言探测合成进读往返(① stat/sha 戳 +
|
|
15
|
+
* base64 -d 探测 + 文件读取一次带回;② CAS 写回用已确定 argv)。编码侧无需
|
|
16
|
+
* 探测:折行输出由解析侧 \s+ 归一消化(base64 < file 全方言通吃);解码侧
|
|
17
|
+
* 不用 `base64 -d || base64 -D` 赌 fallback(GPT 否决:双解码器共用 stdin,
|
|
18
|
+
* 首个消费后第二个拿不到完整载荷)。大文件(base64>30KB)自动回落 fs 层路径。
|
|
13
19
|
*
|
|
14
20
|
* **仅适用 UTF-8 文本**(readFile 返回 UTF-8 字符串;二进制文件的编辑走
|
|
15
21
|
* readBase64 + 消费方自行改写 + writeFile)。
|
|
@@ -31,8 +37,10 @@ export declare class EditConflictError extends Error {
|
|
|
31
37
|
constructor(message: string);
|
|
32
38
|
}
|
|
33
39
|
/**
|
|
34
|
-
*
|
|
35
|
-
* ①
|
|
40
|
+
* 受控编辑(真 2 次往返 + 远端 CAS 原子写回):
|
|
41
|
+
* ① 读+戳+方言探测(1 次往返):`stat 戳; sha 戳; __FXS__; base64 -d 探测;
|
|
42
|
+
* __FXD__; base64 < file` —— (mtime,size)+全文+解码 argv 一次带回
|
|
43
|
+
* (__FXD__ 含下划线不在 base64 字母表——与 __FXS__ 同款防撞)
|
|
36
44
|
* ② 精确替换(本地):0 命中/多处命中(未开 all)拒绝
|
|
37
45
|
* ③ CAS 原子写回(1 次往返):远端一条命令内完成「戳比对 + tmp 写 + mv 原子替换 + 新戳回执」
|
|
38
46
|
* —— 戳不符(他人先写)→ EditConflictError;写后回执新戳
|