@skillfm/local 2.3.0 → 2.5.0

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 (100) hide show
  1. package/dist/doctor.js.map +1 -1
  2. package/dist/guard/cli.d.ts.map +1 -1
  3. package/dist/guard/cli.js.map +1 -1
  4. package/dist/harness/kernels/deny-pipeline.js +1 -1
  5. package/dist/harness/kernels/deny-pipeline.js.map +1 -1
  6. package/dist/harness/writers.d.ts.map +1 -1
  7. package/dist/harness/writers.js +2 -0
  8. package/dist/harness/writers.js.map +1 -1
  9. package/dist/index.js +29 -3
  10. package/dist/index.js.map +1 -1
  11. package/dist/mcp-stdio/api-client.d.ts.map +1 -1
  12. package/dist/mcp-stdio/api-client.js +3 -0
  13. package/dist/mcp-stdio/api-client.js.map +1 -1
  14. package/dist/mcp-stdio/render-flow.d.ts.map +1 -1
  15. package/dist/mcp-stdio/render-flow.js.map +1 -1
  16. package/dist/mcp-stdio/request-context.d.ts.map +1 -1
  17. package/dist/mcp-stdio/request-context.js +1 -0
  18. package/dist/mcp-stdio/request-context.js.map +1 -1
  19. package/dist/mcp-stdio/server.d.ts.map +1 -1
  20. package/dist/mcp-stdio/server.js +75 -3
  21. package/dist/mcp-stdio/server.js.map +1 -1
  22. package/dist/mcp-stdio/sse-progress-client.js.map +1 -1
  23. package/dist/skill-installer/bundle-fetcher.d.ts +40 -0
  24. package/dist/skill-installer/bundle-fetcher.d.ts.map +1 -0
  25. package/dist/skill-installer/bundle-fetcher.js +133 -0
  26. package/dist/skill-installer/bundle-fetcher.js.map +1 -0
  27. package/dist/skill-installer/errors.d.ts +12 -0
  28. package/dist/skill-installer/errors.d.ts.map +1 -0
  29. package/dist/skill-installer/errors.js +42 -0
  30. package/dist/skill-installer/errors.js.map +1 -0
  31. package/dist/skill-installer/index.d.ts +20 -0
  32. package/dist/skill-installer/index.d.ts.map +1 -0
  33. package/dist/skill-installer/index.js +193 -0
  34. package/dist/skill-installer/index.js.map +1 -0
  35. package/dist/skill-installer/lockfile.d.ts +8 -0
  36. package/dist/skill-installer/lockfile.d.ts.map +1 -0
  37. package/dist/skill-installer/lockfile.js +52 -0
  38. package/dist/skill-installer/lockfile.js.map +1 -0
  39. package/dist/skill-installer/npm-installer.d.ts +16 -0
  40. package/dist/skill-installer/npm-installer.d.ts.map +1 -0
  41. package/dist/skill-installer/npm-installer.js +83 -0
  42. package/dist/skill-installer/npm-installer.js.map +1 -0
  43. package/dist/skill-installer/paths.d.ts +4 -0
  44. package/dist/skill-installer/paths.d.ts.map +1 -0
  45. package/dist/skill-installer/paths.js +16 -0
  46. package/dist/skill-installer/paths.js.map +1 -0
  47. package/dist/skill-installer/tar-extractor.d.ts +15 -0
  48. package/dist/skill-installer/tar-extractor.d.ts.map +1 -0
  49. package/dist/skill-installer/tar-extractor.js +56 -0
  50. package/dist/skill-installer/tar-extractor.js.map +1 -0
  51. package/dist/skill-md/template.js +2 -2
  52. package/dist/skill-runner/cli.d.ts +4 -0
  53. package/dist/skill-runner/cli.d.ts.map +1 -0
  54. package/dist/skill-runner/cli.js +81 -0
  55. package/dist/skill-runner/cli.js.map +1 -0
  56. package/dist/skill-runner/discovery.d.ts +3 -0
  57. package/dist/skill-runner/discovery.d.ts.map +1 -0
  58. package/dist/skill-runner/discovery.js +108 -0
  59. package/dist/skill-runner/discovery.js.map +1 -0
  60. package/dist/skill-runner/index.d.ts +9 -0
  61. package/dist/skill-runner/index.d.ts.map +1 -0
  62. package/dist/skill-runner/index.js +100 -0
  63. package/dist/skill-runner/index.js.map +1 -0
  64. package/dist/skill-runner/registry.d.ts +11 -0
  65. package/dist/skill-runner/registry.d.ts.map +1 -0
  66. package/dist/skill-runner/registry.js +79 -0
  67. package/dist/skill-runner/registry.js.map +1 -0
  68. package/dist/skill-runner/spawner.d.ts +14 -0
  69. package/dist/skill-runner/spawner.d.ts.map +1 -0
  70. package/dist/skill-runner/spawner.js +85 -0
  71. package/dist/skill-runner/spawner.js.map +1 -0
  72. package/dist/skill-runner/types.d.ts +62 -0
  73. package/dist/skill-runner/types.d.ts.map +1 -0
  74. package/dist/skill-runner/types.js +6 -0
  75. package/dist/skill-runner/types.js.map +1 -0
  76. package/dist/skill-tunnel/cli.d.ts +5 -0
  77. package/dist/skill-tunnel/cli.d.ts.map +1 -0
  78. package/dist/skill-tunnel/cli.js +205 -0
  79. package/dist/skill-tunnel/cli.js.map +1 -0
  80. package/dist/skill-tunnel/client.d.ts +56 -0
  81. package/dist/skill-tunnel/client.d.ts.map +1 -0
  82. package/dist/skill-tunnel/client.js +260 -0
  83. package/dist/skill-tunnel/client.js.map +1 -0
  84. package/dist/skill-tunnel/handshake.d.ts +35 -0
  85. package/dist/skill-tunnel/handshake.d.ts.map +1 -0
  86. package/dist/skill-tunnel/handshake.js +61 -0
  87. package/dist/skill-tunnel/handshake.js.map +1 -0
  88. package/dist/skill-tunnel/heartbeat.d.ts +34 -0
  89. package/dist/skill-tunnel/heartbeat.d.ts.map +1 -0
  90. package/dist/skill-tunnel/heartbeat.js +86 -0
  91. package/dist/skill-tunnel/heartbeat.js.map +1 -0
  92. package/dist/skill-tunnel/local-bridge.d.ts +30 -0
  93. package/dist/skill-tunnel/local-bridge.d.ts.map +1 -0
  94. package/dist/skill-tunnel/local-bridge.js +224 -0
  95. package/dist/skill-tunnel/local-bridge.js.map +1 -0
  96. package/dist/skill-tunnel/reconnect.d.ts +21 -0
  97. package/dist/skill-tunnel/reconnect.d.ts.map +1 -0
  98. package/dist/skill-tunnel/reconnect.js +72 -0
  99. package/dist/skill-tunnel/reconnect.js.map +1 -0
  100. package/package.json +5 -2
@@ -0,0 +1,81 @@
1
+ // M1 skill-runner — CLI subcommand handlers (invoked from src/index.ts)
2
+ //
3
+ // 对应子命令:
4
+ // - `skillfm-local run-skill <slug>` — 启动本地 skill daemon
5
+ // - `skillfm-local stop-skill <slug>` — 停止并清理
6
+ // - `skillfm-local list-skills` — 查本地已跑的 skill
7
+ import { listSkills, runSkill, stopSkill } from './index.js';
8
+ function parseFlags(args) {
9
+ const positional = [];
10
+ const flags = {};
11
+ for (let i = 0; i < args.length; i += 1) {
12
+ const t = args[i];
13
+ if (t.startsWith('--')) {
14
+ const eq = t.indexOf('=');
15
+ if (eq > 0) {
16
+ flags[t.slice(2, eq)] = t.slice(eq + 1);
17
+ }
18
+ else {
19
+ const next = args[i + 1];
20
+ if (next !== undefined && !next.startsWith('--')) {
21
+ flags[t.slice(2)] = next;
22
+ i += 1;
23
+ }
24
+ else {
25
+ flags[t.slice(2)] = true;
26
+ }
27
+ }
28
+ }
29
+ else {
30
+ positional.push(t);
31
+ }
32
+ }
33
+ return { positional, flags };
34
+ }
35
+ export async function cmdRunSkill() {
36
+ const { positional, flags } = parseFlags(process.argv.slice(3));
37
+ const slug = positional[0];
38
+ if (!slug) {
39
+ console.error(JSON.stringify({
40
+ ok: false,
41
+ error: 'MISSING_SLUG',
42
+ message: 'Usage: skillfm-local run-skill <slug> [--bundle-root=<path>] [--start-daemon]',
43
+ }));
44
+ process.exit(1);
45
+ }
46
+ const result = await runSkill({
47
+ slug,
48
+ bundle_root_override: typeof flags['bundle-root'] === 'string' ? flags['bundle-root'] : undefined,
49
+ start_daemon: flags['start-daemon'] === true,
50
+ health_timeout_ms: typeof flags['health-timeout-ms'] === 'string'
51
+ ? Number.parseInt(flags['health-timeout-ms'], 10)
52
+ : undefined,
53
+ });
54
+ // 单行 JSON 输出,方便 agent parse
55
+ console.log(JSON.stringify(result));
56
+ process.exit(result.ok ? 0 : 1);
57
+ }
58
+ export async function cmdStopSkill() {
59
+ const { positional } = parseFlags(process.argv.slice(3));
60
+ const slug = positional[0];
61
+ if (!slug) {
62
+ console.error(JSON.stringify({
63
+ ok: false,
64
+ error: 'MISSING_SLUG',
65
+ message: 'Usage: skillfm-local stop-skill <slug>',
66
+ }));
67
+ process.exit(1);
68
+ }
69
+ const result = await stopSkill(slug);
70
+ console.log(JSON.stringify(result));
71
+ process.exit(result.ok ? 0 : 1);
72
+ }
73
+ export function cmdListSkills() {
74
+ const skills = listSkills();
75
+ console.log(JSON.stringify({
76
+ ok: true,
77
+ count: Object.keys(skills).length,
78
+ skills,
79
+ }, null, 2));
80
+ }
81
+ //# sourceMappingURL=cli.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../../src/skill-runner/cli.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { SkillBundleLocation } from './types.js';
2
+ export declare function discoverSkillBundle(slug: string, bundleRootOverride?: string): SkillBundleLocation;
3
+ //# sourceMappingURL=discovery.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.d.ts","sourceRoot":"","sources":["../../src/skill-runner/discovery.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAwEtD,wBAAgB,mBAAmB,CACjC,IAAI,EAAE,MAAM,EACZ,kBAAkB,CAAC,EAAE,MAAM,GAC1B,mBAAmB,CAyDrB"}
@@ -0,0 +1,108 @@
1
+ // M1 skill-runner — skill bundle 查找 + manifest 解析
2
+ //
3
+ // 支持两种 bundle 位置(优先级从高到低):
4
+ // 1. 显式 env `SKILLFM_SKILL_BUNDLE_ROOT=/path/to/monorepo` → 按 `solutions/<slug>/` 找(开发模式)
5
+ // 2. `~/.skillfm/skills/<slug>@<version>/`(生产安装目录,未来 `skillfm install` 创建)
6
+ //
7
+ // manifest 解析:只读需要的最小字段(slug / version / runtime.endpoint),不做完整 schema 校验
8
+ // (完整校验归 M6 manifest validator)。
9
+ import { readFileSync, existsSync } from 'node:fs';
10
+ import { join } from 'node:path';
11
+ import { homedir } from 'node:os';
12
+ const DEFAULT_USER_BUNDLE_ROOT = join(homedir(), '.skillfm', 'skills');
13
+ function parseEndpointPort(endpoint) {
14
+ const match = endpoint.match(/^https?:\/\/(?:127\.0\.0\.1|localhost):(\d+)(?:\/|$)/);
15
+ if (!match) {
16
+ throw new Error(`runtime.endpoint 必须是 http://127.0.0.1:<port> 或 http://localhost:<port>,实际: ${endpoint}(BYOK 红线)`);
17
+ }
18
+ const port = Number.parseInt(match[1], 10);
19
+ if (!Number.isInteger(port) || port < 1024 || port > 65535) {
20
+ throw new Error(`runtime.endpoint 端口必须在 1024-65535 范围,实际: ${port}`);
21
+ }
22
+ return port;
23
+ }
24
+ function extractManifestFields(yamlText) {
25
+ // 极简正则——只处理 SkillFM 官方 manifest 规约风格(2 空格缩进,简单标量)
26
+ const pick = (re) => {
27
+ const m = yamlText.match(re);
28
+ return m ? m[1].trim().replace(/^['"]|['"]$/g, '') : null;
29
+ };
30
+ const slug = pick(/^metadata:\n(?:[\s\S]*?\n)? slug:\s*([^\n#]+)/m);
31
+ const version = pick(/^metadata:\n(?:[\s\S]*?\n)? version:\s*([^\n#]+)/m);
32
+ const endpoint = pick(/^runtime:\n(?:[\s\S]*?\n)? endpoint:\s*([^\n#]+)/m);
33
+ const modeRaw = pick(/^runtime:\n(?:[\s\S]*?\n)? execution_mode:\s*([^\n#]+)/m);
34
+ if (!slug)
35
+ throw new Error('manifest 缺 metadata.slug');
36
+ if (!version)
37
+ throw new Error('manifest 缺 metadata.version');
38
+ if (!endpoint)
39
+ throw new Error('manifest 缺 runtime.endpoint');
40
+ const execution_mode = modeRaw === 'docker_shared' ? 'docker_shared' : 'agent_local';
41
+ return { slug, version, endpoint, execution_mode };
42
+ }
43
+ /** 尝试在 monorepo `solutions/<slug>/` 找(开发模式)*/
44
+ function tryMonorepoBundle(slug, monorepoRoot) {
45
+ // slug 可能带 hyphen(xianyu-avatar-adult)或 underscore(xianyu_avatar_adult)
46
+ // solutions 目录用 hyphen
47
+ const candidates = [
48
+ join(monorepoRoot, 'solutions', slug),
49
+ join(monorepoRoot, 'solutions', slug.replace(/_/g, '-')),
50
+ ];
51
+ for (const dir of candidates) {
52
+ if (existsSync(join(dir, 'skill.manifest.yaml')))
53
+ return dir;
54
+ }
55
+ return null;
56
+ }
57
+ /** 尝试在用户安装目录找 */
58
+ function tryUserBundle(slug, userBundleRoot) {
59
+ // 格式:<root>/<slug>@<version>/,取版本最新的
60
+ // M1 骨架:简化为固定 `<slug>` 目录(不带版本),支持 `<slug>@<version>` 作为扩展
61
+ const plain = join(userBundleRoot, slug);
62
+ if (existsSync(join(plain, 'skill.manifest.yaml')))
63
+ return plain;
64
+ // TODO(M2+): 扫描 <slug>@* 目录选最新版
65
+ return null;
66
+ }
67
+ export function discoverSkillBundle(slug, bundleRootOverride) {
68
+ const monorepoRoot = bundleRootOverride ?? process.env.SKILLFM_SKILL_BUNDLE_ROOT ?? null;
69
+ const userBundleRoot = process.env.SKILLFM_USER_BUNDLE_ROOT ?? DEFAULT_USER_BUNDLE_ROOT;
70
+ let bundleDir = null;
71
+ if (monorepoRoot)
72
+ bundleDir = tryMonorepoBundle(slug, monorepoRoot);
73
+ if (!bundleDir)
74
+ bundleDir = tryUserBundle(slug, userBundleRoot);
75
+ if (!bundleDir) {
76
+ throw Object.assign(new Error(`找不到 skill ${slug}。查过: ${monorepoRoot ?? '(SKILLFM_SKILL_BUNDLE_ROOT 未设)'} / ${userBundleRoot}`), { code: 'SKILL_NOT_FOUND' });
77
+ }
78
+ const manifestPath = join(bundleDir, 'skill.manifest.yaml');
79
+ const yaml = readFileSync(manifestPath, 'utf-8');
80
+ const manifest = extractManifestFields(yaml);
81
+ // 校验 slug 匹配(允许 hyphen/underscore 互换)
82
+ const normalize = (s) => s.replace(/[-_]/g, '');
83
+ if (normalize(manifest.slug) !== normalize(slug)) {
84
+ throw new Error(`manifest.slug (${manifest.slug}) 与请求的 slug (${slug}) 不匹配`);
85
+ }
86
+ // BYOK 红线:execution_mode=agent_local 时 endpoint 必须 loopback
87
+ if (manifest.execution_mode === 'agent_local') {
88
+ // parseEndpointPort 内已强制校验 127.0.0.1/localhost
89
+ }
90
+ else {
91
+ throw new Error(`skill ${slug} execution_mode=${manifest.execution_mode},不应由 @skillfm/local run-skill 启动(docker_shared skill 在赵云 Docker 跑)`);
92
+ }
93
+ const port = parseEndpointPort(manifest.endpoint);
94
+ const serverEntry = join(bundleDir, 'runtime', 'server.js');
95
+ const daemonEntry = join(bundleDir, 'runtime', 'daemon.js');
96
+ if (!existsSync(serverEntry)) {
97
+ throw new Error(`skill ${slug} 缺 runtime/server.js —— 确认已 build(cd ${bundleDir} && npm run build)`);
98
+ }
99
+ return {
100
+ slug: manifest.slug,
101
+ version: manifest.version,
102
+ bundle_dir: bundleDir,
103
+ server_entry: serverEntry,
104
+ daemon_entry: existsSync(daemonEntry) ? daemonEntry : null,
105
+ port,
106
+ };
107
+ }
108
+ //# sourceMappingURL=discovery.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"discovery.js","sourceRoot":"","sources":["../../src/skill-runner/discovery.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { RunSkillError, RunSkillOptions, RunSkillResult } from './types.js';
2
+ export declare function runSkill(opts: RunSkillOptions): Promise<RunSkillResult | RunSkillError>;
3
+ export declare function stopSkill(slug: string): Promise<{
4
+ ok: boolean;
5
+ message: string;
6
+ }>;
7
+ export declare function listSkills(): Record<string, import("./types.js").LocalSkillRegistryEntry>;
8
+ export type { RunSkillResult, RunSkillError, RunSkillOptions } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/skill-runner/index.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EACV,aAAa,EACb,eAAe,EACf,cAAc,EACf,MAAM,YAAY,CAAC;AAIpB,wBAAsB,QAAQ,CAC5B,IAAI,EAAE,eAAe,GACpB,OAAO,CAAC,cAAc,GAAG,aAAa,CAAC,CA6EzC;AAED,wBAAsB,SAAS,CAC7B,IAAI,EAAE,MAAM,GACX,OAAO,CAAC;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC,CAQ3C;AAED,wBAAgB,UAAU,iEAGzB;AAED,YAAY,EAAE,cAAc,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,100 @@
1
+ // M1 skill-runner — 对外入口
2
+ //
3
+ // 本文件是 `skillfm-local run-skill <slug>` 子命令的主逻辑。流程:
4
+ // 1. discover bundle(solutions/<slug>/ or ~/.skillfm/skills/<slug>/)
5
+ // 2. 读 manifest → 得 port + execution_mode
6
+ // 3. pruneDeadEntries → 检查是否已有 alive entry(已在跑则返回 ALREADY_RUNNING)
7
+ // 4. spawnSkill → 返回 PID
8
+ // 5. waitForHealthy → 最多等 20s
9
+ // 6. upsertEntry → 写本地 registry
10
+ // 7. 返回 JSON 给 agent
11
+ //
12
+ // 失败不清理子进程(便于诊断);调用者用 kill-skill 子命令收尾。
13
+ import { discoverSkillBundle } from './discovery.js';
14
+ import { findEntry, isAlive, pruneDeadEntries, readRegistry, removeEntry, upsertEntry, } from './registry.js';
15
+ import { killSkill, spawnSkill, waitForHealthy } from './spawner.js';
16
+ const DEFAULT_HEALTH_TIMEOUT_MS = 20_000;
17
+ export async function runSkill(opts) {
18
+ const { slug } = opts;
19
+ // Step 1: prune dead entries + check already running
20
+ pruneDeadEntries();
21
+ const existing = findEntry(slug);
22
+ if (existing && isAlive(existing.server_pid)) {
23
+ return {
24
+ ok: false,
25
+ error: 'ALREADY_RUNNING',
26
+ message: `skill ${slug} 已在跑 (pid=${existing.server_pid}, port=${existing.port})`,
27
+ hint_for_agent: `已经有一个 ${slug} 在本机运行。先 stop-skill 再 run-skill,或直接复用现有 endpoint ${existing.endpoint}`,
28
+ };
29
+ }
30
+ // Step 2: discover bundle + parse manifest
31
+ let location;
32
+ try {
33
+ location = discoverSkillBundle(slug, opts.bundle_root_override);
34
+ }
35
+ catch (err) {
36
+ const e = err;
37
+ return {
38
+ ok: false,
39
+ error: (e.code === 'SKILL_NOT_FOUND'
40
+ ? 'SKILL_NOT_FOUND'
41
+ : 'MANIFEST_INVALID'),
42
+ message: e.message,
43
+ hint_for_agent: e.code === 'SKILL_NOT_FOUND'
44
+ ? `找不到 skill ${slug}。确认已 git clone 仓库并设 SKILLFM_SKILL_BUNDLE_ROOT,或跑 skillfm install ${slug}`
45
+ : `skill ${slug} 的 manifest 损坏: ${e.message}`,
46
+ };
47
+ }
48
+ // Step 3: spawn
49
+ let handle;
50
+ try {
51
+ handle = await spawnSkill({
52
+ location,
53
+ env_overrides: opts.env_overrides,
54
+ start_daemon: opts.start_daemon,
55
+ });
56
+ }
57
+ catch (err) {
58
+ const e = err;
59
+ return {
60
+ ok: false,
61
+ error: 'SPAWN_FAILED',
62
+ message: e.message,
63
+ hint_for_agent: `spawn 失败:${e.message}。检查 Node 版本(>=20)和 bundle 是否已 build`,
64
+ };
65
+ }
66
+ // Step 4: 立即写 registry(哪怕 health 没过也留痕,方便诊断 kill)
67
+ upsertEntry(handle, location.bundle_dir);
68
+ // Step 5: health check
69
+ const healthy = await waitForHealthy(handle.endpoint, opts.health_timeout_ms ?? DEFAULT_HEALTH_TIMEOUT_MS);
70
+ if (!healthy) {
71
+ // Health 失败 —— kill 子进程 + 清 registry
72
+ killSkill(handle);
73
+ removeEntry(slug);
74
+ return {
75
+ ok: false,
76
+ error: 'HEALTH_TIMEOUT',
77
+ message: `skill ${slug} spawn 后 ${opts.health_timeout_ms ?? DEFAULT_HEALTH_TIMEOUT_MS}ms 内未通过 /health 检查`,
78
+ hint_for_agent: `skill ${slug} 启动后不响应。可能原因:端口被占、依赖未装、skill 代码 bug。查看 skill 日志排查`,
79
+ };
80
+ }
81
+ return {
82
+ ok: true,
83
+ handle,
84
+ hint_for_agent: `skill ${slug} 已在本机跑起来 (pid=${handle.server_pid}, endpoint=${handle.endpoint})。cookie/profile 存本节点 BYOK 安全。下一步 skillfm-local tunnel start 连 brain(M2)`,
85
+ };
86
+ }
87
+ export async function stopSkill(slug) {
88
+ const entry = findEntry(slug);
89
+ if (!entry) {
90
+ return { ok: false, message: `skill ${slug} 未在本地 registry 注册` };
91
+ }
92
+ killSkill(entry);
93
+ removeEntry(slug);
94
+ return { ok: true, message: `skill ${slug} 已停止 (pid=${entry.server_pid})` };
95
+ }
96
+ export function listSkills() {
97
+ pruneDeadEntries();
98
+ return readRegistry().skills;
99
+ }
100
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/skill-runner/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ import type { LocalSkillRegistry, LocalSkillRegistryEntry, SkillDaemonHandle } from './types.js';
2
+ export declare function readRegistry(): LocalSkillRegistry;
3
+ export declare function writeRegistry(reg: LocalSkillRegistry): void;
4
+ export declare function upsertEntry(handle: SkillDaemonHandle, bundle_dir: string): void;
5
+ export declare function removeEntry(slug: string): void;
6
+ export declare function findEntry(slug: string): LocalSkillRegistryEntry | null;
7
+ /** 判断 PID 是否仍在跑(M1 简化:kill 0 探活,失败代表进程已死)*/
8
+ export declare function isAlive(pid: number): boolean;
9
+ /** 清理已死进程条目(启动新 skill 前调用)*/
10
+ export declare function pruneDeadEntries(): string[];
11
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/skill-runner/registry.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EACV,kBAAkB,EAClB,uBAAuB,EACvB,iBAAiB,EAClB,MAAM,YAAY,CAAC;AASpB,wBAAgB,YAAY,IAAI,kBAAkB,CAcjD;AAED,wBAAgB,aAAa,CAAC,GAAG,EAAE,kBAAkB,GAAG,IAAI,CAG3D;AAED,wBAAgB,WAAW,CACzB,MAAM,EAAE,iBAAiB,EACzB,UAAU,EAAE,MAAM,GACjB,IAAI,CASN;AAED,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAI9C;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAEtE;AAED,4CAA4C;AAC5C,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAO5C;AAED,6BAA6B;AAC7B,wBAAgB,gBAAgB,IAAI,MAAM,EAAE,CAW3C"}
@@ -0,0 +1,79 @@
1
+ // M1 skill-runner — 本地 skill 注册表 `~/.skillfm/skills.local.json`
2
+ //
3
+ // 功能:
4
+ // - 跟踪本节点跑了哪些 skill daemon(slug → {pid, port, started_at, endpoint})
5
+ // - 跨进程读取(M2 SkillTunnelClient 启动时读这里得到本地 skill 列表,上报给 brain)
6
+ // - `skillfm-local stop-skill <slug>` 清理
7
+ // - `skillfm-local list-skills` 查看
8
+ import { readFileSync, writeFileSync, existsSync, mkdirSync, } from 'node:fs';
9
+ import { join, dirname } from 'node:path';
10
+ import { homedir } from 'node:os';
11
+ const REGISTRY_FILE = join(homedir(), '.skillfm', 'skills.local.json');
12
+ function ensureDir() {
13
+ const dir = dirname(REGISTRY_FILE);
14
+ if (!existsSync(dir))
15
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
16
+ }
17
+ export function readRegistry() {
18
+ if (!existsSync(REGISTRY_FILE)) {
19
+ return { version: 1, skills: {} };
20
+ }
21
+ try {
22
+ const raw = readFileSync(REGISTRY_FILE, 'utf-8');
23
+ const parsed = JSON.parse(raw);
24
+ if (parsed.version !== 1 || !parsed.skills) {
25
+ return { version: 1, skills: {} };
26
+ }
27
+ return parsed;
28
+ }
29
+ catch {
30
+ return { version: 1, skills: {} };
31
+ }
32
+ }
33
+ export function writeRegistry(reg) {
34
+ ensureDir();
35
+ writeFileSync(REGISTRY_FILE, JSON.stringify(reg, null, 2), { mode: 0o600 });
36
+ }
37
+ export function upsertEntry(handle, bundle_dir) {
38
+ const reg = readRegistry();
39
+ const entry = {
40
+ ...handle,
41
+ bundle_dir,
42
+ last_health_at: Date.now(),
43
+ };
44
+ reg.skills[handle.slug] = entry;
45
+ writeRegistry(reg);
46
+ }
47
+ export function removeEntry(slug) {
48
+ const reg = readRegistry();
49
+ delete reg.skills[slug];
50
+ writeRegistry(reg);
51
+ }
52
+ export function findEntry(slug) {
53
+ return readRegistry().skills[slug] ?? null;
54
+ }
55
+ /** 判断 PID 是否仍在跑(M1 简化:kill 0 探活,失败代表进程已死)*/
56
+ export function isAlive(pid) {
57
+ try {
58
+ process.kill(pid, 0);
59
+ return true;
60
+ }
61
+ catch {
62
+ return false;
63
+ }
64
+ }
65
+ /** 清理已死进程条目(启动新 skill 前调用)*/
66
+ export function pruneDeadEntries() {
67
+ const reg = readRegistry();
68
+ const removed = [];
69
+ for (const [slug, entry] of Object.entries(reg.skills)) {
70
+ if (!isAlive(entry.server_pid)) {
71
+ removed.push(slug);
72
+ delete reg.skills[slug];
73
+ }
74
+ }
75
+ if (removed.length > 0)
76
+ writeRegistry(reg);
77
+ return removed;
78
+ }
79
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../src/skill-runner/registry.ts"],"names":[],"mappings":"AAAA,gEAAgE;AAChE,EAAE;AACF,MAAM;AACN,qEAAqE;AACrE,8DAA8D;AAC9D,yCAAyC;AACzC,mCAAmC;AAEnC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,UAAU,EACV,SAAS,GACV,MAAM,SAAS,CAAC;AACjB,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAOlC,MAAM,aAAa,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,UAAU,EAAE,mBAAmB,CAAC,CAAC;AAEvE,SAAS,SAAS;IAChB,MAAM,GAAG,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IACnC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AACzE,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,IAAI,CAAC,UAAU,CAAC,aAAa,CAAC,EAAE,CAAC;QAC/B,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpC,CAAC;IACD,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC;QACjD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAuB,CAAC;QACrD,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC;YAC3C,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACpC,CAAC;QACD,OAAO,MAAM,CAAC;IAChB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;IACpC,CAAC;AACH,CAAC;AAED,MAAM,UAAU,aAAa,CAAC,GAAuB;IACnD,SAAS,EAAE,CAAC;IACZ,aAAa,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,MAAM,UAAU,WAAW,CACzB,MAAyB,EACzB,UAAkB;IAElB,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,KAAK,GAA4B;QACrC,GAAG,MAAM;QACT,UAAU;QACV,cAAc,EAAE,IAAI,CAAC,GAAG,EAAE;KAC3B,CAAC;IACF,GAAG,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC;IAChC,aAAa,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,WAAW,CAAC,IAAY;IACtC,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;IACxB,aAAa,CAAC,GAAG,CAAC,CAAC;AACrB,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,OAAO,YAAY,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,IAAI,CAAC;AAC7C,CAAC;AAED,4CAA4C;AAC5C,MAAM,UAAU,OAAO,CAAC,GAAW;IACjC,IAAI,CAAC;QACH,OAAO,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;QACrB,OAAO,IAAI,CAAC;IACd,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,6BAA6B;AAC7B,MAAM,UAAU,gBAAgB;IAC9B,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;YAC/B,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACnB,OAAO,GAAG,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC;IACH,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,aAAa,CAAC,GAAG,CAAC,CAAC;IAC3C,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { SkillBundleLocation, SkillDaemonHandle } from './types.js';
2
+ export interface SpawnSkillParams {
3
+ location: SkillBundleLocation;
4
+ env_overrides?: Record<string, string>;
5
+ start_daemon?: boolean;
6
+ /** 子进程 stdout/stderr 写入的日志文件(可选,默认继承 parent stdout)*/
7
+ log_file?: string;
8
+ }
9
+ export declare function spawnSkill(params: SpawnSkillParams): Promise<SkillDaemonHandle>;
10
+ /** Poll GET {endpoint}/health 直到 200 或超时 */
11
+ export declare function waitForHealthy(endpoint: string, timeoutMs: number): Promise<boolean>;
12
+ /** Kill a running skill process tree. Returns true if kill signal delivered. */
13
+ export declare function killSkill(handle: Pick<SkillDaemonHandle, 'server_pid' | 'daemon_pid'>): boolean;
14
+ //# sourceMappingURL=spawner.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.d.ts","sourceRoot":"","sources":["../../src/skill-runner/spawner.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAEzE,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,mBAAmB,CAAC;IAC9B,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACvC,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,sDAAsD;IACtD,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAuBD,wBAAsB,UAAU,CAC9B,MAAM,EAAE,gBAAgB,GACvB,OAAO,CAAC,iBAAiB,CAAC,CAmC5B;AAED,4CAA4C;AAC5C,wBAAsB,cAAc,CAClC,QAAQ,EAAE,MAAM,EAChB,SAAS,EAAE,MAAM,GAChB,OAAO,CAAC,OAAO,CAAC,CAoBlB;AAED,gFAAgF;AAChF,wBAAgB,SAAS,CAAC,MAAM,EAAE,IAAI,CAAC,iBAAiB,EAAE,YAAY,GAAG,YAAY,CAAC,GAAG,OAAO,CAa/F"}
@@ -0,0 +1,85 @@
1
+ // M1 skill-runner — skill 子进程 spawn + health check
2
+ //
3
+ // 设计原则:
4
+ // - 一旦 spawn 成功,立即返回 PID 给调用者(不阻塞等 health ready)
5
+ // - health check 另起一次异步 poll,失败不 kill 子进程(交给调用者决定)—— 方便诊断
6
+ import { spawn } from 'node:child_process';
7
+ import { setTimeout as sleep } from 'node:timers/promises';
8
+ function spawnEntry(entryPath, env, label) {
9
+ const proc = spawn(process.execPath, [entryPath], {
10
+ env,
11
+ detached: true,
12
+ stdio: 'ignore',
13
+ });
14
+ if (!proc.pid) {
15
+ throw Object.assign(new Error(`spawn ${label} 失败:pid 未返回`), { code: 'SPAWN_FAILED' });
16
+ }
17
+ // 脱离 parent 事件循环,允许 @skillfm/local 退出后子进程继续跑
18
+ proc.unref();
19
+ return proc;
20
+ }
21
+ export async function spawnSkill(params) {
22
+ const { location, env_overrides, start_daemon } = params;
23
+ const env = {
24
+ ...process.env,
25
+ ...env_overrides,
26
+ SKILL_HOST: '127.0.0.1',
27
+ SKILL_PORT: String(location.port),
28
+ };
29
+ const serverProc = spawnEntry(location.server_entry, env, `${location.slug} server`);
30
+ let daemonPid = null;
31
+ if (start_daemon && location.daemon_entry) {
32
+ const daemonProc = spawnEntry(location.daemon_entry, env, `${location.slug} daemon`);
33
+ daemonPid = daemonProc.pid ?? null;
34
+ }
35
+ return {
36
+ slug: location.slug,
37
+ version: location.version,
38
+ port: location.port,
39
+ server_pid: serverProc.pid,
40
+ daemon_pid: daemonPid,
41
+ started_at: new Date().toISOString(),
42
+ endpoint: `http://127.0.0.1:${location.port}`,
43
+ };
44
+ }
45
+ /** Poll GET {endpoint}/health 直到 200 或超时 */
46
+ export async function waitForHealthy(endpoint, timeoutMs) {
47
+ const healthUrl = `${endpoint}/health`;
48
+ const deadline = Date.now() + timeoutMs;
49
+ let attempt = 0;
50
+ while (Date.now() < deadline) {
51
+ attempt += 1;
52
+ try {
53
+ const controller = new AbortController();
54
+ const timer = setTimeout(() => controller.abort(), 2000);
55
+ const res = await fetch(healthUrl, { signal: controller.signal });
56
+ clearTimeout(timer);
57
+ if (res.ok)
58
+ return true;
59
+ }
60
+ catch {
61
+ // fall through to sleep
62
+ }
63
+ // 指数退避但 cap 在 1s
64
+ const delay = Math.min(200 * 2 ** Math.min(attempt, 3), 1000);
65
+ await sleep(delay);
66
+ }
67
+ return false;
68
+ }
69
+ /** Kill a running skill process tree. Returns true if kill signal delivered. */
70
+ export function killSkill(handle) {
71
+ let killed = false;
72
+ for (const pid of [handle.server_pid, handle.daemon_pid]) {
73
+ if (pid && pid > 0) {
74
+ try {
75
+ process.kill(pid, 'SIGTERM');
76
+ killed = true;
77
+ }
78
+ catch {
79
+ // Process may already be dead — swallow
80
+ }
81
+ }
82
+ }
83
+ return killed;
84
+ }
85
+ //# sourceMappingURL=spawner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"spawner.js","sourceRoot":"","sources":["../../src/skill-runner/spawner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,62 @@
1
+ export interface SkillBundleLocation {
2
+ /** skill slug(manifest.metadata.slug)*/
3
+ slug: string;
4
+ /** skill 语义版本(manifest.metadata.version)*/
5
+ version: string;
6
+ /** bundle 根目录绝对路径 */
7
+ bundle_dir: string;
8
+ /** runtime server 入口脚本绝对路径(默认 <bundle>/runtime/server.js)*/
9
+ server_entry: string;
10
+ /** runtime daemon 入口脚本绝对路径(可选)*/
11
+ daemon_entry: string | null;
12
+ /** loopback 监听端口,从 manifest runtime.endpoint 解析 */
13
+ port: number;
14
+ }
15
+ export interface SkillDaemonHandle {
16
+ slug: string;
17
+ version: string;
18
+ port: number;
19
+ /** server 子进程 PID */
20
+ server_pid: number;
21
+ /** daemon 子进程 PID(可选,M1 默认不启动 daemon 进程)*/
22
+ daemon_pid: number | null;
23
+ started_at: string;
24
+ /** loopback URL —— 永远 127.0.0.1,守 §1.5 BYOK 红线 */
25
+ endpoint: string;
26
+ }
27
+ export interface LocalSkillRegistryEntry extends SkillDaemonHandle {
28
+ /** skill bundle 目录(方便 stop 命令清理时直接找)*/
29
+ bundle_dir: string;
30
+ /** 上次 health check 成功时间(ms timestamp)*/
31
+ last_health_at: number;
32
+ }
33
+ /** `~/.skillfm/skills.local.json` 顶层结构 */
34
+ export interface LocalSkillRegistry {
35
+ version: 1;
36
+ skills: Record<string, LocalSkillRegistryEntry>;
37
+ }
38
+ export interface RunSkillOptions {
39
+ /** skill slug,例如 `xianyu-avatar-adult` */
40
+ slug: string;
41
+ /** 可选:bundle 查找根目录覆盖。默认 env `SKILLFM_SKILL_BUNDLE_ROOT` 或 `~/.skillfm/skills` */
42
+ bundle_root_override?: string;
43
+ /** health check 轮询超时(默认 20s)*/
44
+ health_timeout_ms?: number;
45
+ /** 是否同时启动 daemon 子进程(默认 false —— M1 先只启动 server)*/
46
+ start_daemon?: boolean;
47
+ /** 注入到 skill 子进程的环境变量(用于 cookie 路径等 BYOK 配置)*/
48
+ env_overrides?: Record<string, string>;
49
+ }
50
+ /** run-skill CLI 输出(成功时)*/
51
+ export interface RunSkillResult {
52
+ ok: true;
53
+ handle: SkillDaemonHandle;
54
+ hint_for_agent: string;
55
+ }
56
+ export interface RunSkillError {
57
+ ok: false;
58
+ error: 'SKILL_NOT_FOUND' | 'MANIFEST_INVALID' | 'ALREADY_RUNNING' | 'PORT_CONFLICT' | 'SPAWN_FAILED' | 'HEALTH_TIMEOUT';
59
+ message: string;
60
+ hint_for_agent: string;
61
+ }
62
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/skill-runner/types.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,mBAAmB;IAClC,wCAAwC;IACxC,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAChB,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,CAAC;IACrB,iCAAiC;IACjC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mDAAmD;IACnD,IAAI,EAAE,MAAM,CAAC;CACd;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,qBAAqB;IACrB,UAAU,EAAE,MAAM,CAAC;IACnB,2CAA2C;IAC3C,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,kDAAkD;IAClD,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,uBAAwB,SAAQ,iBAAiB;IAChE,uCAAuC;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,wCAAwC;IACxC,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,0CAA0C;AAC1C,MAAM,WAAW,kBAAkB;IACjC,OAAO,EAAE,CAAC,CAAC;IACX,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC;CACjD;AAED,MAAM,WAAW,eAAe;IAC9B,0CAA0C;IAC1C,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,+BAA+B;IAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,mDAAmD;IACnD,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,+CAA+C;IAC/C,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACxC;AAED,2BAA2B;AAC3B,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,IAAI,CAAC;IACT,MAAM,EAAE,iBAAiB,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,aAAa;IAC5B,EAAE,EAAE,KAAK,CAAC;IACV,KAAK,EACD,iBAAiB,GACjB,kBAAkB,GAClB,iBAAiB,GACjB,eAAe,GACf,cAAc,GACd,gBAAgB,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC;IAChB,cAAc,EAAE,MAAM,CAAC;CACxB"}
@@ -0,0 +1,6 @@
1
+ // M1 skill-runner — shared types
2
+ //
3
+ // 本文件是 @skillfm/local skill daemon 管理模块的对外类型。其它 subagent(M2 tunnel client)
4
+ // 会依赖这里的 SkillDaemonHandle / LocalSkillRegistryEntry,不依赖内部实现。
5
+ export {};
6
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/skill-runner/types.ts"],"names":[],"mappings":"AAAA,iCAAiC;AACjC,EAAE;AACF,2EAA2E;AAC3E,8DAA8D"}
@@ -0,0 +1,5 @@
1
+ export declare function cmdTunnelStart(): Promise<void>;
2
+ export declare function cmdTunnelStop(): void;
3
+ export declare function cmdTunnelStatus(): void;
4
+ export declare function cmdTunnel(): Promise<void>;
5
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../../src/skill-tunnel/cli.ts"],"names":[],"mappings":"AA2EA,wBAAsB,cAAc,IAAI,OAAO,CAAC,IAAI,CAAC,CAyFpD;AAED,wBAAgB,aAAa,IAAI,IAAI,CA8BpC;AAED,wBAAgB,eAAe,IAAI,IAAI,CAQtC;AAED,wBAAsB,SAAS,IAAI,OAAO,CAAC,IAAI,CAAC,CAwB/C"}