Commit 3012d8a0 by luoqi

fix(ai/script/skills): resolve skills dir from cwd, not __dirname

dev (nest start --watch --builder swc) 编译产物在 dist/src/modules/...,
__dirname 指向 dist/src/.../draft-plan-script,__dirname/skills 找不到
(nest-cli.json assets 只 copy 到 dist/modules/...,SWC + tsc 两态目录不同)。

改用 cwd-based 多路径 resolver(跟 sync.service.ts 同模式):
  1. env PAC_SCRIPT_SKILLS_DIR 优先
  2. src/modules/.../skills 存在则用(dev 直接读源 MD,无需 watchAssets)
  3. 回退 dist/modules/.../skills(prod docker 只含 dist,nest build tsc 已 copy)

registry + composer 共用 resolveScriptSkillsRoot 导出函数。dev/prod 都 work。
parent 52ca8c28
......@@ -7,6 +7,7 @@ import {
type SkillMatchContext,
} from './skill.types';
import type { DraftPlanScriptInput } from './input.types';
import { resolveScriptSkillsRoot } from './skill-registry.service';
/**
* SkillComposer — 纯函数式,把 input + 全 skills → matched skills + system prompt。
......@@ -33,11 +34,9 @@ export interface ComposedSystem {
composeHash: string;
}
/** base-system.md 路径(跟 skill-registry 同根目录策略,但在 skills/ 根下) */
/** base-system.md 路径(跟 registry 共用 cwd-based 多路径 resolver) */
function resolveBaseSystemPath(): string {
const override = process.env.PAC_SCRIPT_SKILLS_DIR;
if (override) return join(override, 'base-system.md');
return join(__dirname, 'skills', 'base-system.md');
return join(resolveScriptSkillsRoot(), 'base-system.md');
}
/** lazy load base system,只读 1 次缓存 */
......
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { readdirSync, readFileSync, statSync } from 'node:fs';
import { existsSync, readdirSync, readFileSync, statSync } from 'node:fs';
import { join } from 'node:path';
import { load as yamlLoad } from 'js-yaml';
import {
......@@ -8,6 +8,27 @@ import {
} from './skill.types';
/**
* 解析 skills/ 根目录(模块级,registry + composer 共用)。
*
* 路径策略(env 优先 → src → dist):
* - env PAC_SCRIPT_SKILLS_DIR:eval / 测试切目录
* - src/modules/.../skills:dev 模式(SWC 编译产物在 dist/src/...,__dirname 不可靠;
* 源文件始终在 src/,直接读最快)
* - dist/modules/.../skills:prod docker(image 只含 dist/,nest-cli.json `assets`
* 已 copy SKILL.md 到 dist/modules/.../skills/)
*
* 这跟 sync.service.ts 用 cwd 而非 __dirname 是同一个原因 — SWC dev 跟 tsc prod 的
* 编译输出目录结构不同,__dirname 不能跨态稳定;cwd 在 dev/prod 都是 apps/pac-service 根。
*/
export function resolveScriptSkillsRoot(): string {
const override = process.env.PAC_SCRIPT_SKILLS_DIR;
if (override) return override;
const src = join(process.cwd(), 'src/modules/ai/calls/draft-plan-script/skills');
if (existsSync(src)) return src;
return join(process.cwd(), 'dist/modules/ai/calls/draft-plan-script/skills');
}
/**
* SkillRegistryService — 启动时扫描 SKILL.md,parse frontmatter + body,
* 校验后索引到 Map<name, Skill>。
*
......@@ -59,19 +80,8 @@ export class DraftPlanScriptSkillRegistry implements OnModuleInit {
return this.skills.get(name);
}
/**
* skills/ 目录解析。
*
* 路径策略:env PAC_SCRIPT_SKILLS_DIR 优先(eval / 测试切目录用),
* 否则 __dirname/skills:
* - prod 容器:dist/modules/ai/calls/draft-plan-script/skills(nest-cli assets 拷贝)
* - dev (swc): 同 prod,assets 已 watchAssets
* - ts-jest: src/modules/.../skills(ts-jest 直接跑 src)
*/
private resolveSkillsRoot(): string {
const override = process.env.PAC_SCRIPT_SKILLS_DIR;
if (override) return override;
return join(__dirname, 'skills');
return resolveScriptSkillsRoot();
}
/** 递归 scan,返回所有 SKILL.md 绝对路径 */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment