Skip to content

(WIP) feat: add support drivers for afs, providing multiple views for the node.#855

Open
lban2049 wants to merge 23 commits into
mainfrom
feat-afs-view-driver
Open

(WIP) feat: add support drivers for afs, providing multiple views for the node.#855
lban2049 wants to merge 23 commits into
mainfrom
feat-afs-view-driver

Conversation

@lban2049

@lban2049 lban2049 commented Dec 25, 2025

Copy link
Copy Markdown
Contributor

Related Issue

Major Changes

Screenshots

Test Plan

Checklist

  • This change requires documentation updates, and I have updated the relevant documentation. If the documentation has not been updated, please create a documentation update issue and link it here
  • The changes are already covered by tests, and I have adjusted the test coverage for the changed parts
  • The newly added code logic is also covered by tests
  • This change adds dependencies, and they are placed in dependencies and devDependencies
  • This change includes adding or updating npm dependencies, and it does not result in multiple versions of the same dependency [check the diff of pnpm-lock.yaml]

Summary by AIGNE

Release Notes

New Feature:

  • Added i18n (internationalization) driver support for automatic file translation across multiple languages
  • Introduced view-based content transformation system allowing files to be processed through configurable drivers
  • Added batch prefetching capabilities for improved performance when working with multiple file views

Refactor:

  • Migrated from context-based presets to a flexible driver-based architecture
  • Replaced pagination with view-based content access in AFS read operations
  • Enhanced CLI with dynamic driver loading support for extensible functionality

@github-actions

github-actions Bot commented Dec 25, 2025

Copy link
Copy Markdown

Image description AIGNE CodeSmith

Walkthrough

This changeset introduces a comprehensive view-based architecture to the AFS (Abstract File System) with driver support for content transformation. The implementation adds metadata management with SQLite storage, view processing with caching and state management, and an i18n driver for multilingual file translation. The system replaces context-based presets with a driver architecture, enabling dynamic content projections while maintaining backward compatibility through fallback mechanisms.

Changes

Files Summary
afs/core/src/metadata/* CRITICAL ISSUES: Migration hash comparison logic bug, missing error handling, and lack of transaction safety. Establishes metadata management system with SQLite storage for tracking source files and view projections, including migration system and table schemas.
afs/core/src/afs.ts, afs/core/src/view-processor.ts, afs/core/src/view-schema.ts, afs/core/src/type.ts, afs/core/src/index.ts Adds driver support and view-based architecture to AFS class with ViewProcessor for content transformation, caching, and batch operations. Includes dynamic schema building and enhanced read/write operations.
afs/core/test/view-driver.test.ts CRITICAL ISSUES: Grammar error in comment, unclear variable naming (zh), and vague error handling comment. Comprehensive test coverage for view drivers with mock i18n translation driver and file system.
afs/i18n-driver/* Complete i18n driver implementation with TypeScript dual package exports, translation agent, and multilingual file support. Includes build configurations for CommonJS/ESM and comprehensive test coverage.
packages/cli/src/utils/load-aigne.ts Adds i18n driver support to CLI by extending available drivers array with dynamic import of @aigne/afs-i18n-driver module.
packages/core/src/loader/*, packages/core/test/loader/* Refactors agent schema system from context-based presets to driver-based architecture with discriminated unions, dynamic schema generation, and AFS configuration changes from context to drivers.
packages/core/src/prompt/skills/afs/read.ts Refactors AFSReadAgent to support view drivers, replacing pagination with view projections and line numbering. Adds dynamic schema building and view status tracking.

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

Commits Files that changed from the base of the PR and between 2f9427c and bb1e7c7 commits.
Files selected (29)
  • afs/core/src/afs.ts (7)
  • afs/core/src/index.ts (1)
  • afs/core/src/metadata/index.ts (1)
  • afs/core/src/metadata/migrate.ts (1)
  • afs/core/src/metadata/migrations/001-init.ts (1)
  • afs/core/src/metadata/models/index.ts (1)
  • afs/core/src/metadata/models/source-metadata.ts (1)
  • afs/core/src/metadata/models/view-metadata.ts (1)
  • afs/core/src/metadata/store.ts (1)
  • afs/core/src/metadata/type.ts (1)
  • afs/core/src/type.ts (2)
  • afs/core/src/view-processor.ts (1)
  • afs/core/src/view-schema.ts (1)
  • afs/core/test/view-driver.test.ts (1)
  • afs/i18n-driver/scripts/tsconfig.build.cjs.json (1)
  • afs/i18n-driver/scripts/tsconfig.build.dts.json (1)
  • afs/i18n-driver/scripts/tsconfig.build.esm.json (1)
  • afs/i18n-driver/scripts/tsconfig.build.json (1)
  • afs/i18n-driver/src/default-translation-agent.ts (1)
  • afs/i18n-driver/src/driver.ts (1)
  • afs/i18n-driver/src/index.ts (1)
  • afs/i18n-driver/src/storage.ts (1)
  • afs/i18n-driver/test/i18n-driver.test.ts (1)
  • afs/i18n-driver/tsconfig.json (1)
  • packages/cli/src/utils/load-aigne.ts (1)
  • packages/core/src/loader/agent-yaml.ts (9)
  • packages/core/src/loader/index.ts (7)
  • packages/core/src/prompt/skills/afs/read.ts (1)
  • packages/core/test/loader/agent-yaml.test.ts (1)
Files ignored due to filter (9)
  • afs/core/package.json
  • afs/i18n-driver.md
  • afs/i18n-driver/CHANGELOG.md
  • afs/i18n-driver/README.md
  • afs/i18n-driver/package.json
  • packages/cli/package.json
  • packages/core/test-agents/test-afs-driver.yaml
  • packages/core/test-agents/test-afs-storage.yaml
  • pnpm-lock.yaml
Files skipped from review due to trivial changes (6)
  • afs/i18n-driver/scripts/tsconfig.build.cjs.json
  • afs/i18n-driver/scripts/tsconfig.build.dts.json
  • afs/i18n-driver/scripts/tsconfig.build.esm.json
  • afs/i18n-driver/scripts/tsconfig.build.json
  • afs/i18n-driver/tsconfig.json
  • packages/core/test/loader/agent-yaml.test.ts
Review comments generated (66)
  • Review: 12
  • LGTM: 54

提示

Image description AIGNE CodeSmith (@codesmith) 聊天

  • 回复此机器人留下的审查评论以提出后续问题。审查评论是对差异或文件的评论。
  • 通过在回复中标记 @codesmith 邀请机器人加入审查评论链。

代码建议

  • 机器人可能会提出代码建议,但在提交前请仔细审查它们,因为行号范围可能会不对齐。
  • 你可以编辑机器人做出的评论,并在建议稍有偏差时手动调整。

暂停增量审查

  • 在 PR 描述中的任何位置添加 @codesmith: ignore 以暂停机器人的进一步审查。

pathIdx: index("idx_view_path").on(table.path),
stateIdx: index("idx_view_state").on(table.state),
derivedFromIdx: index("idx_view_derived_from").on(table.derivedFrom),
uniqueModulePathView: index("unique_module_path_view").on(table.module, table.path, table.view),

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

The index name suggests it should be unique, but it's created as a regular index instead of a unique index.

-    uniqueModulePathView: index("unique_module_path_view").on(table.module, table.path, table.view),
+    uniqueModulePathView: index("unique_module_path_view").on(table.module, table.path, table.view).unique(),

Comment thread afs/core/src/type.ts
Comment on lines +44 to +48
/**
* View represents different projections of the same file
* V1: Only language dimension is implemented
* Future: format, policy, variant dimensions
*/

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

The comment contains a grammatical error and unclear wording.

- * View represents different projections of the same file
- * V1: Only language dimension is implemented
- * Future: format, policy, variant dimensions
+ * View represents different projections of the same file.
+ * V1: Only the language dimension is implemented.
+ * Future: format, policy, variant dimensions will be added.

Comment thread afs/core/src/type.ts
Comment on lines +56 to +61
/**
* Wait strategy for view processing
* - strict: Wait for view generation to complete before returning
* - fallback: Return source immediately and trigger background generation
*/
export type WaitStrategy = "strict" | "fallback";

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

The comment contains a grammatical error in the fallback description.

- * - fallback: Return source immediately and trigger background generation
+ * - fallback: Returns source immediately and triggers background generation

Comment thread afs/core/src/type.ts
Comment on lines +63 to +69
/**
* View status in read result
* Indicates whether the requested view was returned or fell back to source
*/
export interface ViewStatus {
fallback?: boolean; // true = returned source content, view is being generated in background
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

The comment contains unclear wording that could be confusing.

- * Indicates whether the requested view was returned or fell back to source
+ * Indicates whether the requested view was returned or if it fell back to the source

* Process a view (generate or regenerate)
* V1: Direct execution without job deduplication
*/
async processView(module: AFSModule, path: string, view: View, context: any): Promise<AFSEntry> {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

The context parameter should have a more specific type instead of any for better type safety.

-  async processView(module: AFSModule, path: string, view: View, context: any): Promise<AFSEntry> {
+  async processView(module: AFSModule, path: string, view: View, context: unknown): Promise<AFSEntry> {

},
);

expect(result.result.content).toBe("Hello,World!This is aTest。");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

There's a spacing issue in the expected translation result.

-  expect(result.result.content).toBe("Hello,World!This is aTest。");
+  expect(result.result.content).toBe("Hello,World!This is a Test。");

// Function config - we can't know drivers without calling it
// Return empty array as we can't determine drivers at construction time
return [];
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

There's a missing closing brace for the if statement.

-    return [];
-   }
+    return [];
+  }

"Wait strategy: 'strict' waits for view generation (default), 'fallback' returns source immediately",
),
});
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

Inconsistent indentation - should use 2 spaces to match the rest of the file.

-      }
+    }

.split("\n")
.map((line, idx) => `${idx + 1}| ${line}`)
.join("\n");
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

Inconsistent indentation - should use 2 spaces to match the rest of the file.

-      }
+    }

Comment on lines 149 to 160
return {
status: "success",
tool: "afs_read",
path: input.path,
totalLines,
returnedLines,
truncated,
offset,
message,
withLineNumbers: input.withLineNumbers,
...result,
data: {
data: result.data && {
...result.data,
content: processedContent,
content,
},
};
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Image description AIGNE CodeSmith

Inconsistent indentation - should use 2 spaces to match the rest of the file.

-     return {
-       status: "success",
-       tool: "afs_read",
-       path: input.path,
-      withLineNumbers: input.withLineNumbers,
-       ...result,
-      data: result.data && {
-         ...result.data,
-        content,
-      },
-    };
+    return {
+      status: "success",
+      tool: "afs_read",
+      path: input.path,
+      withLineNumbers: input.withLineNumbers,
+      ...result,
+      data: result.data && {
+        ...result.data,
+        content,
+      },
+    };

@li-yechao li-yechao requested a review from Copilot December 29, 2025 01:35

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds support for AFS drivers, enabling a view-based content transformation system. The primary use case is providing multiple language versions of files through an i18n driver, which can automatically translate content on demand.

Key Changes:

  • Introduced a driver architecture allowing files to be processed through configurable transformations (views)
  • Implemented i18n driver for automatic file translation across multiple languages
  • Added metadata storage system to track source files and generated views
  • Extended AFS read operations to support view parameters and wait strategies

Reviewed changes

Copilot reviewed 37 out of 38 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
packages/core/src/loader/index.ts Added driver loading and initialization logic to support AFS drivers configuration
packages/core/src/loader/agent-yaml.ts Extended YAML schema to support drivers and storage configuration
packages/core/src/prompt/skills/afs/read.ts Added view and wait parameters to read skill with viewStatus output
packages/cli/src/utils/load-aigne.ts Registered i18n driver as available driver for CLI
afs/i18n-driver/* New package implementing i18n translation driver
afs/core/src/* Core AFS extensions for view processing, metadata, and driver support
Files not reviewed (1)
  • pnpm-lock.yaml: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +238 to +267
const modules: AFSModule[] = [];
for (const m of agent.afs.modules || []) {
const moduleName = typeof m === "string" ? m : m.module;

const mod = options?.afs?.availableModules?.find(
(mod) => mod.module === moduleName || mod.alias?.includes(moduleName),
);
if (!mod) throw new Error(`AFS module not found: ${typeof m === "string" ? m : m.module}`);

const module = await mod.load({
filepath: path,
parsed: typeof m === "string" ? {} : m.options,
});

modules.push(module);
}

// Create drivers
const drivers: AFSDriver[] = [];
for (const d of agent.afs.drivers || []) {
const driverName = typeof d === "string" ? d : d.driver;

const drv = options?.afs?.availableDrivers?.find(
(drv) => drv.driver === driverName || drv.alias?.includes(driverName),
);
if (!drv) throw new Error(`AFS driver not found: ${typeof d === "string" ? d : d.driver}`);

const driver = await drv.load({
parsed: typeof d === "string" ? {} : d.options,
});

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Line 267 pushes module to the modules array instead of driver to the drivers array. This should be drivers.push(driver); to correctly populate the drivers array.

Copilot uses AI. Check for mistakes.
Comment on lines +354 to +357
async cleanupFailedViews(_olderThan?: Date): Promise<void> {
const db = await this.db;
// Note: drizzle doesn't have a direct < operator for dates
// For now, we delete all failed views regardless of age

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The olderThan parameter is prefixed with underscore indicating it's unused, but the method signature doesn't match the interface requirement. Either implement the date filtering logic or document why it's not implemented and keep the parameter for interface compliance.

Suggested change
async cleanupFailedViews(_olderThan?: Date): Promise<void> {
const db = await this.db;
// Note: drizzle doesn't have a direct < operator for dates
// For now, we delete all failed views regardless of age
/**
* Remove metadata entries for failed views.
*
* @param olderThan - Optional timestamp from the MetadataStore interface. Currently
* ignored in this SQLite implementation: due to limitations in the underlying
* query builder, we do not yet filter by age and instead delete all failed views.
* The parameter is kept for interface compatibility and future extension.
*/
async cleanupFailedViews(olderThan?: Date): Promise<void> {
const db = await this.db;
// Explicitly ignore `olderThan` for now; see documentation above.
void olderThan;
// Note: drizzle doesn't have a direct < operator for dates.
// For now, we delete all failed views regardless of age.

Copilot uses AI. Check for mistakes.
Comment on lines +31 to +35
// translationAgent: optionalize(
// z.custom<Agent<TranslationInput, TranslationOutput>>(
// (value) => value instanceof Agent<TranslationInput, TranslationOutput>,
// ),
// ),

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Commented-out code should be removed rather than left in the codebase. If the translationAgent field validation is intentionally excluded, add a comment explaining why.

Suggested change
// translationAgent: optionalize(
// z.custom<Agent<TranslationInput, TranslationOutput>>(
// (value) => value instanceof Agent<TranslationInput, TranslationOutput>,
// ),
// ),
// Note: translationAgent is intentionally not validated here; the Agent type
// is provided and checked at the type level by consumers of this driver.

Copilot uses AI. Check for mistakes.
Comment thread afs/i18n-driver/README.md
Comment on lines +24 to +28
const i18nDriver = new I18nDriver({
context,
defaultSourceLanguage: "zh",
supportedLanguages: ["en", "ja", "ko"],
});

Copilot AI Dec 29, 2025

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The README shows context as a required parameter in the I18nDriver constructor options, but the actual implementation (driver.ts:63) doesn't include context in the I18nDriverOptions interface. The documentation is inconsistent with the implementation.

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants