@ai-zen/agents-sdk 0.3.1 → 0.3.3

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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,34 @@
1
1
  # Changelog
2
2
 
3
+ ## [0.3.3] - 2026-07-27
4
+
5
+ ### 🎯 优化
6
+
7
+ - **默认 SubAgent System Prompt 新增两条强制性要求**:
8
+ 1. 信息不明确/模糊/缺失时拒绝执行,要求补充
9
+ 2. 存在自相矛盾信息时指出矛盾,要求澄清
10
+ - **默认 Agent System Prompt 新增原则**:"有矛盾就问 — 如果用户指令中存在自相矛盾之处,应指出矛盾并请求澄清,而不是自行取舍"
11
+ - **默认 SubAgent `function.description` 和 `task` 参数描述**同步更新,强调不明确信息将导致拒绝执行
12
+
13
+ ## [0.3.2] - 2026-07-26
14
+
15
+ ### 💥 破坏性变更
16
+
17
+ - **`EntityRepository` 所有方法改为异步** — `list()`、`read()`、`write()`、`delete()` 现在返回 `Promise`,需 `await`
18
+ - **`DraftRepository` 所有方法改为异步** — `read()`、`write()`、`delete()` 需 `await`
19
+ - **`ConfigManager` 所有方法改为异步** — `read()`、`write()`、`ensureDirs()`、`ensureDefaultAgent()`、`ensureDefaultSubAgent()`、`ensureDefaultConfig()`、`bootstrap()` 均需 `await`
20
+ - **`createAgent()` 恢复为 `async`** — 因底层仓储改为异步,`createAgent(provider, agentId)` 需 `await`
21
+ - **`AutoDraftPlugin.checkDraftForRestore()` 改为异步** — 需 `await`
22
+
23
+ ### 🎯 优化
24
+
25
+ - **全面消除同步文件 IO** — 所有生产代码中的 `existsSync`、`readFileSync`、`writeFileSync`、`readdirSync`、`mkdirSync`、`unlinkSync`、`renameSync` 全部替换为 `fs.promises` 异步 API,避免事件循环阻塞
26
+ - **`skillTools.ts` — 工具回调中的 `readdirSync` 替换为 `fs.promises.readdir`**
27
+
28
+ ### ✅ 测试
29
+
30
+ - 7 个测试文件同步更新为 `async`/`await`,测试辅助函数也使用 `fs.promises`
31
+
3
32
  ## [0.3.1] - 2026-07-26
4
33
 
5
34
  ### 💥 破坏性变更
@@ -3,7 +3,7 @@ import { SdkAgent } from "../../runtime/SdkAgent.js";
3
3
  import { createDisclosureParam } from "../disclosure.js";
4
4
  import { readSkill } from "../discovery/skills.js";
5
5
  import { createLogger } from "../../shared/logger.js";
6
- import { readdirSync } from "node:fs";
6
+ import { promises as fs } from "node:fs";
7
7
  const log = createLogger();
8
8
  const EMPTY_HINT = "(当前没有可用的 Skill,请联系用户添加)";
9
9
  /**
@@ -44,7 +44,7 @@ export function createLoadSkillTool(skillDirs, filteredSkills) {
44
44
  // 扫描 skill 目录下的文件列表
45
45
  let fileList = "";
46
46
  try {
47
- const entries = readdirSync(skill.dirPath, { withFileTypes: true });
47
+ const entries = await fs.readdir(skill.dirPath, { withFileTypes: true });
48
48
  const files = entries.map((e) => {
49
49
  const suffix = e.isDirectory() ? "/" : "";
50
50
  return ` - ${e.name}${suffix}`;
@@ -9,17 +9,17 @@ export declare class ConfigManager {
9
9
  /**
10
10
  * 读取配置。文件不存在时返回出厂默认配置。
11
11
  */
12
- read(): AppConfig;
13
- write(config: AppConfig): void;
12
+ read(): Promise<AppConfig>;
13
+ write(config: AppConfig): Promise<void>;
14
14
  /**
15
15
  * 确保基础目录结构存在。
16
16
  * 创建 basePath 及所有标准共享子目录(agents/、sub-agents/、skills/ 等)。
17
17
  */
18
- ensureDirs(): void;
18
+ ensureDirs(): Promise<void>;
19
19
  /**
20
20
  * 确保 config.json 存在。不存在时写入出厂默认配置 DSL。
21
21
  */
22
- ensureDefaultConfig(): AppConfig;
22
+ ensureDefaultConfig(): Promise<AppConfig>;
23
23
  /**
24
24
  * 确保 basePath/agents/default.json 存在。
25
25
  *
@@ -27,7 +27,7 @@ export declare class ConfigManager {
27
27
  * - agents/ 为空 → 写入默认 Agent
28
28
  * - 已有其他 Agent → 返回 null
29
29
  */
30
- ensureDefaultAgent(): AgentDefinition | null;
30
+ ensureDefaultAgent(): Promise<AgentDefinition | null>;
31
31
  /**
32
32
  * 确保 basePath/sub-agents/{DEFAULT_SUBAGENT_ID}.json 存在。
33
33
  *
@@ -35,15 +35,15 @@ export declare class ConfigManager {
35
35
  * - sub-agents/ 为空 → 写入默认通用助手 SubAgent
36
36
  * - 已有其他 SubAgent → 返回 null
37
37
  */
38
- ensureDefaultSubAgent(): AgentDefinition | null;
38
+ ensureDefaultSubAgent(): Promise<AgentDefinition | null>;
39
39
  /**
40
40
  * 一键初始化:目录 + config.json + 默认 Agent + 默认 SubAgent。
41
41
  * 已有文件不会被覆盖。
42
42
  */
43
- bootstrap(): {
43
+ bootstrap(): Promise<{
44
44
  config: AppConfig;
45
45
  agent: AgentDefinition | null;
46
46
  subAgent: AgentDefinition | null;
47
- };
47
+ }>;
48
48
  }
49
49
  export { DEFAULT_AGENT_ID, DEFAULT_AGENT_DEFINITION, DEFAULT_SUBAGENT_ID, DEFAULT_SUBAGENT_DEFINITION, DEFAULT_APP_CONFIG, CONFIG_SUB_DIRS, } from "./constants.js";
@@ -1,4 +1,4 @@
1
- import { readFileSync, writeFileSync, existsSync, renameSync, mkdirSync, readdirSync } from "node:fs";
1
+ import { promises as fs } from "node:fs";
2
2
  import { dirname, join } from "node:path";
3
3
  import { DEFAULT_AGENT_ID, DEFAULT_AGENT_DEFINITION, DEFAULT_SUBAGENT_ID, DEFAULT_SUBAGENT_DEFINITION, DEFAULT_APP_CONFIG, CONFIG_SUB_DIRS, } from "./constants.js";
4
4
  /**
@@ -17,21 +17,27 @@ export class ConfigManager {
17
17
  /**
18
18
  * 读取配置。文件不存在时返回出厂默认配置。
19
19
  */
20
- read() {
21
- if (!existsSync(this.configPath)) {
20
+ async read() {
21
+ try {
22
+ await fs.access(this.configPath);
23
+ }
24
+ catch {
22
25
  return { ...DEFAULT_APP_CONFIG };
23
26
  }
24
- const raw = readFileSync(this.configPath, "utf-8");
27
+ const raw = await fs.readFile(this.configPath, "utf-8");
25
28
  return JSON.parse(raw);
26
29
  }
27
- write(config) {
30
+ async write(config) {
28
31
  const dir = dirname(this.configPath);
29
- if (!existsSync(dir)) {
30
- mkdirSync(dir, { recursive: true });
32
+ try {
33
+ await fs.access(dir);
34
+ }
35
+ catch {
36
+ await fs.mkdir(dir, { recursive: true });
31
37
  }
32
38
  const tmpPath = this.configPath + ".tmp";
33
- writeFileSync(tmpPath, JSON.stringify(config, null, 2), "utf-8");
34
- renameSync(tmpPath, this.configPath);
39
+ await fs.writeFile(tmpPath, JSON.stringify(config, null, 2), "utf-8");
40
+ await fs.rename(tmpPath, this.configPath);
35
41
  }
36
42
  // -----------------------------------------------------------------------
37
43
  // 目录 & 默认实体
@@ -40,22 +46,25 @@ export class ConfigManager {
40
46
  * 确保基础目录结构存在。
41
47
  * 创建 basePath 及所有标准共享子目录(agents/、sub-agents/、skills/ 等)。
42
48
  */
43
- ensureDirs() {
44
- mkdirSync(this.basePath, { recursive: true });
49
+ async ensureDirs() {
50
+ await fs.mkdir(this.basePath, { recursive: true });
45
51
  for (const dir of CONFIG_SUB_DIRS) {
46
- mkdirSync(join(this.basePath, dir), { recursive: true });
52
+ await fs.mkdir(join(this.basePath, dir), { recursive: true });
47
53
  }
48
54
  }
49
55
  /**
50
56
  * 确保 config.json 存在。不存在时写入出厂默认配置 DSL。
51
57
  */
52
- ensureDefaultConfig() {
53
- if (existsSync(this.configPath)) {
54
- return this.read();
58
+ async ensureDefaultConfig() {
59
+ try {
60
+ await fs.access(this.configPath);
61
+ return await this.read();
62
+ }
63
+ catch {
64
+ await this.ensureDirs();
65
+ await this.write(DEFAULT_APP_CONFIG);
66
+ return { ...DEFAULT_APP_CONFIG };
55
67
  }
56
- this.ensureDirs();
57
- this.write(DEFAULT_APP_CONFIG);
58
- return { ...DEFAULT_APP_CONFIG };
59
68
  }
60
69
  /**
61
70
  * 确保 basePath/agents/default.json 存在。
@@ -64,14 +73,25 @@ export class ConfigManager {
64
73
  * - agents/ 为空 → 写入默认 Agent
65
74
  * - 已有其他 Agent → 返回 null
66
75
  */
67
- ensureDefaultAgent() {
76
+ async ensureDefaultAgent() {
68
77
  const agentsDir = join(this.basePath, "agents");
69
78
  const defaultPath = join(agentsDir, `${DEFAULT_AGENT_ID}.json`);
70
- if (existsSync(defaultPath)) {
71
- return JSON.parse(readFileSync(defaultPath, "utf-8"));
79
+ try {
80
+ await fs.access(defaultPath);
81
+ return JSON.parse(await fs.readFile(defaultPath, "utf-8"));
82
+ }
83
+ catch {
84
+ // default.json 不存在,继续
85
+ }
86
+ await fs.mkdir(agentsDir, { recursive: true });
87
+ let existing;
88
+ try {
89
+ const allFiles = await fs.readdir(agentsDir);
90
+ existing = allFiles.filter((f) => f.endsWith(".json"));
91
+ }
92
+ catch {
93
+ existing = [];
72
94
  }
73
- mkdirSync(agentsDir, { recursive: true });
74
- const existing = readdirSync(agentsDir).filter((f) => f.endsWith(".json"));
75
95
  if (existing.length > 0) {
76
96
  return null;
77
97
  }
@@ -81,7 +101,7 @@ export class ConfigManager {
81
101
  createdAt: now,
82
102
  updatedAt: now,
83
103
  };
84
- writeFileSync(defaultPath, JSON.stringify(definition, null, 2), "utf-8");
104
+ await fs.writeFile(defaultPath, JSON.stringify(definition, null, 2), "utf-8");
85
105
  return definition;
86
106
  }
87
107
  /**
@@ -91,14 +111,25 @@ export class ConfigManager {
91
111
  * - sub-agents/ 为空 → 写入默认通用助手 SubAgent
92
112
  * - 已有其他 SubAgent → 返回 null
93
113
  */
94
- ensureDefaultSubAgent() {
114
+ async ensureDefaultSubAgent() {
95
115
  const subDir = join(this.basePath, "sub-agents");
96
116
  const defaultPath = join(subDir, `${DEFAULT_SUBAGENT_ID}.json`);
97
- if (existsSync(defaultPath)) {
98
- return JSON.parse(readFileSync(defaultPath, "utf-8"));
117
+ try {
118
+ await fs.access(defaultPath);
119
+ return JSON.parse(await fs.readFile(defaultPath, "utf-8"));
120
+ }
121
+ catch {
122
+ // 文件不存在,继续
123
+ }
124
+ await fs.mkdir(subDir, { recursive: true });
125
+ let existing;
126
+ try {
127
+ const allFiles = await fs.readdir(subDir);
128
+ existing = allFiles.filter((f) => f.endsWith(".json"));
129
+ }
130
+ catch {
131
+ existing = [];
99
132
  }
100
- mkdirSync(subDir, { recursive: true });
101
- const existing = readdirSync(subDir).filter((f) => f.endsWith(".json"));
102
133
  if (existing.length > 0) {
103
134
  return null;
104
135
  }
@@ -108,18 +139,18 @@ export class ConfigManager {
108
139
  createdAt: now,
109
140
  updatedAt: now,
110
141
  };
111
- writeFileSync(defaultPath, JSON.stringify(definition, null, 2), "utf-8");
142
+ await fs.writeFile(defaultPath, JSON.stringify(definition, null, 2), "utf-8");
112
143
  return definition;
113
144
  }
114
145
  /**
115
146
  * 一键初始化:目录 + config.json + 默认 Agent + 默认 SubAgent。
116
147
  * 已有文件不会被覆盖。
117
148
  */
118
- bootstrap() {
119
- this.ensureDirs();
120
- const config = this.ensureDefaultConfig();
121
- const agent = this.ensureDefaultAgent();
122
- const subAgent = this.ensureDefaultSubAgent();
149
+ async bootstrap() {
150
+ await this.ensureDirs();
151
+ const config = await this.ensureDefaultConfig();
152
+ const agent = await this.ensureDefaultAgent();
153
+ const subAgent = await this.ensureDefaultSubAgent();
123
154
  return { config, agent, subAgent };
124
155
  }
125
156
  }
@@ -15,10 +15,11 @@ export const DEFAULT_AGENT_DEFINITION = {
15
15
  content: `你是一个严谨可靠的智能助手。请用中文回复,说话风格参照官方文件。
16
16
 
17
17
  - 开动脑筋 — 主动思考、灵活运用工具,而不是机械执行
18
- - 实事求是 — 知之为知之,不知为不知,而不是凭空编造
18
+ - 实事求是 — 知之为知之,不知为不知,而不是凭空编造;如果用户意图不明确,应先提问澄清,而不是自行脑补
19
19
  - 一切行动听指挥 — 严格遵循用户指令,而不是自作主张
20
20
  - 安全第一 — 风险操作先告知确认,而不是盲目执行
21
- - 能打胜仗 — 写优秀的代码,而不是只限于能用的代码`,
21
+ - 能打胜仗 — 写优秀的代码,而不是只限于能用的代码
22
+ - 有矛盾就问 — 如果用户指令中存在自相矛盾之处,应指出矛盾并请求澄清,而不是自行取舍`,
22
23
  },
23
24
  ],
24
25
  permissions: {
@@ -41,7 +42,7 @@ export const DEFAULT_SUBAGENT_DEFINITION = {
41
42
  messages: [
42
43
  {
43
44
  role: AgentNS.Role.System,
44
- content: "你是一个通用助手子 Agent,被父 Agent 委派来独立完成具体任务。请根据给定的任务描述,主动调用你的工具(文件读写、执行命令、搜索等)来分析和完成任务。完成任务后直接返回结果,不需要解释你的思考过程。",
45
+ content: "你是一个通用助手子 Agent,被父 Agent 委派来独立完成具体任务。请根据给定的任务描述,主动调用你的工具(文件读写、执行命令、搜索等)来分析和完成任务。完成任务后直接返回结果,不需要解释你的思考过程。\n\n⚠️ 强制性要求:\n1. 如果任务描述中存在任何不明确、模糊或缺失的信息(包括但不限于具体目标、文件路径、约束条件、预期产出等),你必须直接拒绝执行,并明确列出哪些信息不明确或缺失,要求父 Agent 提供更完整的任务上下文。不得自行假设、猜测或脑补任何信息。\n2. 如果任务描述中存在自相矛盾的信息(如相互冲突的要求、不一致的文件路径、矛盾的约束条件等),你必须及时指出矛盾之处,并要求父 Agent 澄清后再执行。",
45
46
  },
46
47
  { role: AgentNS.Role.User, content: "{{task}}" },
47
48
  ],
@@ -53,11 +54,11 @@ export const DEFAULT_SUBAGENT_DEFINITION = {
53
54
  },
54
55
  function: {
55
56
  name: "sub_agent_default",
56
- description: "通用子 Agent,可独立完成各类任务。委派任务时必须提供完整的任务上下文,包括所有必要的背景信息、文件路径、具体要求和约束条件,确保子 Agent 无需追问即可独立执行。",
57
+ description: "通用子 Agent,可独立完成各类任务。⚠️ 委派任务时必须提供完整的任务上下文,包括所有必要的背景信息、文件路径、具体要求和约束条件,任何信息不明确将导致子 Agent 拒绝执行并要求补充信息。",
57
58
  parameters: {
58
59
  type: "object",
59
60
  properties: {
60
- task: { type: "string", description: "完整的任务描述,必须包含所有必要的背景、目标、约束条件和上下文信息" },
61
+ task: { type: "string", description: "完整的任务描述,必须包含所有必要的背景、目标、约束条件和上下文信息。任何不明确的信息将导致子 Agent 拒绝执行。" },
61
62
  },
62
63
  required: ["task"],
63
64
  additionalProperties: false,
@@ -9,7 +9,7 @@ export declare class DraftRepository {
9
9
  private dir;
10
10
  constructor(dir: string);
11
11
  private path;
12
- read(conversationId?: string): Draft | null;
13
- write(draft: Draft): void;
14
- delete(conversationId?: string): void;
12
+ read(conversationId?: string): Promise<Draft | null>;
13
+ write(draft: Draft): Promise<void>;
14
+ delete(conversationId?: string): Promise<void>;
15
15
  }
@@ -1,4 +1,4 @@
1
- import { readFileSync, writeFileSync, existsSync, unlinkSync, mkdirSync } from "node:fs";
1
+ import { promises as fs } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  const CURRENT_DRAFT = "_current.json";
4
4
  /**
@@ -15,27 +15,38 @@ export class DraftRepository {
15
15
  path(conversationId) {
16
16
  return join(this.dir, conversationId ? `${conversationId}.json` : CURRENT_DRAFT);
17
17
  }
18
- read(conversationId) {
18
+ async read(conversationId) {
19
19
  const p = this.path(conversationId);
20
- if (!existsSync(p))
20
+ try {
21
+ await fs.access(p);
22
+ }
23
+ catch {
21
24
  return null;
25
+ }
22
26
  try {
23
- return JSON.parse(readFileSync(p, "utf-8"));
27
+ return JSON.parse(await fs.readFile(p, "utf-8"));
24
28
  }
25
29
  catch {
26
30
  return null;
27
31
  }
28
32
  }
29
- write(draft) {
30
- if (!existsSync(this.dir)) {
31
- mkdirSync(this.dir, { recursive: true });
33
+ async write(draft) {
34
+ try {
35
+ await fs.access(this.dir);
32
36
  }
33
- writeFileSync(this.path(draft.conversationId), JSON.stringify(draft, null, 2), "utf-8");
37
+ catch {
38
+ await fs.mkdir(this.dir, { recursive: true });
39
+ }
40
+ await fs.writeFile(this.path(draft.conversationId), JSON.stringify(draft, null, 2), "utf-8");
34
41
  }
35
- delete(conversationId) {
42
+ async delete(conversationId) {
36
43
  const p = this.path(conversationId);
37
- if (existsSync(p)) {
38
- unlinkSync(p);
44
+ try {
45
+ await fs.access(p);
46
+ await fs.unlink(p);
47
+ }
48
+ catch {
49
+ // 文件不存在,忽略
39
50
  }
40
51
  }
41
52
  }
@@ -22,5 +22,5 @@ export declare class AutoDraftPlugin implements AgentPlugin {
22
22
  private options;
23
23
  constructor(options: AutoDraftOptions);
24
24
  onInnerLoopEnd(ctx: SendContext): Promise<void>;
25
- static checkDraftForRestore(draftsDir: string): Draft | null;
25
+ static checkDraftForRestore(draftsDir: string): Promise<Draft | null>;
26
26
  }
@@ -1,6 +1,6 @@
1
1
  import { DraftRepository } from "../crud/DraftRepository.js";
2
2
  import { createLogger } from "../shared/logger.js";
3
- import { existsSync } from "node:fs";
3
+ import { promises as fs } from "node:fs";
4
4
  import { join } from "node:path";
5
5
  import dayjs from "dayjs";
6
6
  const log = createLogger();
@@ -34,23 +34,27 @@ export class AutoDraftPlugin {
34
34
  updatedAt: new Date().toISOString(),
35
35
  };
36
36
  const repo = new DraftRepository(draftsDir);
37
- repo.write(draft);
37
+ await repo.write(draft);
38
38
  }
39
39
  catch (err) {
40
40
  log.error(`[autoDraft] 保存失败: ${err?.message ?? err}`);
41
41
  }
42
42
  }
43
- static checkDraftForRestore(draftsDir) {
43
+ static async checkDraftForRestore(draftsDir) {
44
44
  const path = join(draftsDir, CURRENT_DRAFT);
45
- if (!existsSync(path))
45
+ try {
46
+ await fs.access(path);
47
+ }
48
+ catch {
46
49
  return null;
50
+ }
47
51
  const repo = new DraftRepository(draftsDir);
48
- const draft = repo.read();
52
+ const draft = await repo.read();
49
53
  if (!draft)
50
54
  return null;
51
55
  const age = dayjs().diff(dayjs(draft.updatedAt), "day");
52
56
  if (age > EXPIRE_DAYS) {
53
- repo.delete();
57
+ await repo.delete();
54
58
  return null;
55
59
  }
56
60
  return draft;
@@ -1,7 +1,7 @@
1
1
  import { SdkAgent } from "./SdkAgent.js";
2
2
  import type { Provider } from "./Provider.js";
3
3
  /**
4
- * 从磁盘创建 Agent(异步)。
4
+ * 从磁盘创建 Agent。
5
5
  *
6
6
  * 通过 Provider 获取已发现的能力,读取 Agent 定义,过滤并实例化工具,产出 SdkAgent。
7
7
  *
@@ -2,7 +2,7 @@ import { AgentRepository } from "../crud/AgentRepository.js";
2
2
  import { SdkAgent } from "./SdkAgent.js";
3
3
  import { createModel } from "./createModel.js";
4
4
  /**
5
- * 从磁盘创建 Agent(异步)。
5
+ * 从磁盘创建 Agent。
6
6
  *
7
7
  * 通过 Provider 获取已发现的能力,读取 Agent 定义,过滤并实例化工具,产出 SdkAgent。
8
8
  *
@@ -12,7 +12,7 @@ import { createModel } from "./createModel.js";
12
12
  * ```
13
13
  */
14
14
  export async function createAgent(provider, agentId) {
15
- const definition = new AgentRepository(provider.agentsDir).read(agentId);
15
+ const definition = await new AgentRepository(provider.agentsDir).read(agentId);
16
16
  if (!definition)
17
17
  throw new Error(`Agent "${agentId}" 不存在`);
18
18
  const modelId = definition.modelId ?? provider.config.defaultModel;
@@ -14,11 +14,11 @@ export declare class EntityRepository<T extends {
14
14
  /** 获取实体的文件路径 */
15
15
  protected path(id: string): string;
16
16
  /** 列出目录下所有实体(跳过解析失败的文件) */
17
- list(): T[];
17
+ list(): Promise<T[]>;
18
18
  /** 读取单个实体,不存在返回 null */
19
- read(id: string): T | null;
19
+ read(id: string): Promise<T | null>;
20
20
  /** 写入实体(创建或更新) */
21
- write(entity: T): void;
21
+ write(entity: T): Promise<void>;
22
22
  /** 删除实体,不存在时不抛异常 */
23
- delete(id: string): void;
23
+ delete(id: string): Promise<void>;
24
24
  }
@@ -1,4 +1,4 @@
1
- import { readFileSync, writeFileSync, existsSync, unlinkSync, readdirSync, mkdirSync } from "node:fs";
1
+ import { promises as fs } from "node:fs";
2
2
  import { join } from "node:path";
3
3
  /**
4
4
  * 通用实体仓储 — 对磁盘 JSON 文件的 CRUD 操作。
@@ -18,27 +18,36 @@ export class EntityRepository {
18
18
  return join(this.dir, `${id}.json`);
19
19
  }
20
20
  /** 列出目录下所有实体(跳过解析失败的文件) */
21
- list() {
22
- if (!existsSync(this.dir))
21
+ async list() {
22
+ try {
23
+ await fs.access(this.dir);
24
+ }
25
+ catch {
23
26
  return [];
24
- const ids = readdirSync(this.dir)
27
+ }
28
+ const entries = await fs.readdir(this.dir);
29
+ const ids = entries
25
30
  .filter((f) => f.endsWith(".json"))
26
31
  .map((f) => f.replace(/\.json$/, ""));
27
32
  const entities = [];
28
33
  for (const id of ids) {
29
- const entity = this.read(id);
34
+ const entity = await this.read(id);
30
35
  if (entity)
31
36
  entities.push(entity);
32
37
  }
33
38
  return entities;
34
39
  }
35
40
  /** 读取单个实体,不存在返回 null */
36
- read(id) {
41
+ async read(id) {
37
42
  const p = this.path(id);
38
- if (!existsSync(p))
43
+ try {
44
+ await fs.access(p);
45
+ }
46
+ catch {
39
47
  return null;
48
+ }
40
49
  try {
41
- const raw = readFileSync(p, "utf-8");
50
+ const raw = await fs.readFile(p, "utf-8");
42
51
  return JSON.parse(raw);
43
52
  }
44
53
  catch {
@@ -46,17 +55,24 @@ export class EntityRepository {
46
55
  }
47
56
  }
48
57
  /** 写入实体(创建或更新) */
49
- write(entity) {
50
- if (!existsSync(this.dir)) {
51
- mkdirSync(this.dir, { recursive: true });
58
+ async write(entity) {
59
+ try {
60
+ await fs.access(this.dir);
61
+ }
62
+ catch {
63
+ await fs.mkdir(this.dir, { recursive: true });
52
64
  }
53
- writeFileSync(this.path(entity.id), JSON.stringify(entity, null, 2), "utf-8");
65
+ await fs.writeFile(this.path(entity.id), JSON.stringify(entity, null, 2), "utf-8");
54
66
  }
55
67
  /** 删除实体,不存在时不抛异常 */
56
- delete(id) {
68
+ async delete(id) {
57
69
  const p = this.path(id);
58
- if (existsSync(p)) {
59
- unlinkSync(p);
70
+ try {
71
+ await fs.access(p);
72
+ await fs.unlink(p);
73
+ }
74
+ catch {
75
+ // 文件不存在,忽略
60
76
  }
61
77
  }
62
78
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-zen/agents-sdk",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "AI-Zen Agents SDK — shared business logic for CLI and Desktop",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",