mirror of
https://github.com/AIPexStudio/AIPex.git
synced 2026-05-13 18:51:35 +00:00
chore: update LOGIC_INCONSISTENCIES_BY_PACKAGE.md and implement refreshSkillMetadata method
- Updated the status and impact of the `organize_tabs` tool in LOGIC_INCONSISTENCIES_BY_PACKAGE.md, noting its removal from the default bundle. - Resolved naming inconsistencies for the `ungroup_tabs` tool in the tab-groups module. - Implemented the `refreshSkillMetadata` method in SkillManager to update skill metadata from SKILL.md, including validation and error handling.
This commit is contained in:
@@ -140,33 +140,41 @@
|
||||
|
||||
### 2.3 `organize_tabs` Is a Stub (AI Grouping Disabled)
|
||||
|
||||
**Status**: ⚠️ Mitigated | **Tool removed from default bundle**
|
||||
|
||||
|
||||
| Legacy | New |
|
||||
| ------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| `aipex/src/mcp-servers/tab-groups.ts` → `groupTabsByAI()` with full LLM prompt | `new-aipex/packages/browser-runtime/src/tools/tab.ts` → returns `{ success: false, message: "...requires additional implementation..." }` |
|
||||
|
||||
|
||||
**Impact**: Core feature (smart tab grouping) non-functional.
|
||||
**Impact**: ~~Core feature (smart tab grouping) non-functional.~~ Tool is no longer exposed to users.
|
||||
|
||||
**Priority**: P0
|
||||
**Priority**: N/A — Mitigated
|
||||
|
||||
**Migration target**: `packages/browser-runtime`
|
||||
**Migration target**: N/A (tool removed from `allBrowserTools`)
|
||||
|
||||
**Resolution**: The `organize_tabs` tool has been removed from `allBrowserTools` in `packages/browser-runtime/src/tools/index.ts`. The implementation code is retained for future completion of AI-powered tab grouping. The tool is listed in the "Disabled tools" comment block.
|
||||
|
||||
---
|
||||
|
||||
### 2.4 Tab-Group Tool Naming Inconsistency
|
||||
|
||||
**Status**: ✅ Resolved
|
||||
|
||||
|
||||
| Tool | Legacy name | New (tab.ts) | New (tab-groups/index.ts) |
|
||||
| ----------- | -------------- | -------------- | ------------------------- |
|
||||
| Ungroup all | `ungroup_tabs` | `ungroup_tabs` | `ungroup_all_tabs` |
|
||||
| Ungroup all | `ungroup_tabs` | `ungroup_tabs` | `ungroup_tabs` |
|
||||
|
||||
|
||||
**Impact**: Skill scripts / prompts referencing old names may break.
|
||||
**Impact**: ~~Skill scripts / prompts referencing old names may break.~~ Resolved.
|
||||
|
||||
**Priority**: P1
|
||||
**Priority**: N/A — Resolved
|
||||
|
||||
**Migration target**: Consolidate naming in `packages/browser-runtime`
|
||||
**Migration target**: N/A
|
||||
|
||||
**Resolution**: The `ungroupAllTabsTool` in `packages/browser-runtime/src/tools/tools/tab-groups/index.ts` has been renamed from `ungroup_all_tabs` to `ungroup_tabs` for consistency with the legacy naming convention. A comment has been added warning against registering both tools simultaneously to avoid duplicate name conflicts.
|
||||
|
||||
---
|
||||
|
||||
@@ -222,17 +230,21 @@
|
||||
|
||||
### 2.8 Skill System: `refreshSkillMetadata()` Missing
|
||||
|
||||
**Status**: ✅ Resolved
|
||||
|
||||
|
||||
| Legacy | New |
|
||||
| ---------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------- |
|
||||
| `aipex/src/skill/lib/services/skill-manager.ts` has `refreshSkillMetadata()` | Not present in `new-aipex/packages/browser-runtime/src/skill/lib/services/skill-manager.ts` |
|
||||
| `aipex/src/skill/lib/services/skill-manager.ts` has `refreshSkillMetadata()` | `new-aipex/packages/browser-runtime/src/skill/lib/services/skill-manager.ts` now has `refreshSkillMetadata()` |
|
||||
|
||||
|
||||
**Impact**: Skill metadata may become stale after updates.
|
||||
**Impact**: ~~Skill metadata may become stale after updates.~~ Resolved.
|
||||
|
||||
**Priority**: P2
|
||||
**Priority**: N/A — Resolved
|
||||
|
||||
**Migration target**: `packages/browser-runtime`
|
||||
**Migration target**: N/A
|
||||
|
||||
**Resolution**: The `refreshSkillMetadata(skillId: string)` method has been ported to the new `SkillManager`. It reads `SKILL.md` from ZenFS, parses frontmatter, updates IndexedDB metadata via `skillStorage.updateSkill()`, refreshes the registry cache via `skillRegistry.updateSkill()`, and emits a `skill_loaded` event with type `skill_metadata_refreshed`. Path traversal is guarded by rejecting skill IDs containing `/`, `\\`, or `..`.
|
||||
|
||||
---
|
||||
|
||||
@@ -321,10 +333,10 @@
|
||||
|
||||
| Priority | Items |
|
||||
| -------- | ---------------------------------------- |
|
||||
| P0 | 2.1, 2.2, 2.3, 6 |
|
||||
| P1 | ~~1.1~~, ~~1.2~~ (completed), 2.4, 2.5, 2.7, 3.1, 4.2 (auth) |
|
||||
| P2 | ~~1.3~~ (superseded), 2.6, 2.8, 4.2 (non-auth) |
|
||||
| Closed | 1.1 (acceptable difference), 1.2 (resolved), 1.3 (superseded) |
|
||||
| P0 | 2.1, 2.2, 6 |
|
||||
| P1 | ~~1.1~~, ~~1.2~~ (completed), ~~2.4~~ (resolved), 2.5, 2.7, 3.1, 4.2 (auth) |
|
||||
| P2 | ~~1.3~~ (superseded), 2.6, ~~2.8~~ (resolved), 4.2 (non-auth) |
|
||||
| Closed | 1.1 (acceptable difference), 1.2 (resolved), 1.3 (superseded), 2.3 (mitigated), 2.4 (resolved), 2.8 (resolved) |
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -450,6 +450,106 @@ export class SkillManager {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Refresh skill metadata from SKILL.md file.
|
||||
* This is called when SKILL.md is edited and saved via the file manager.
|
||||
* It re-parses the frontmatter and updates both IndexedDB and the registry.
|
||||
*/
|
||||
async refreshSkillMetadata(skillId: string): Promise<void> {
|
||||
if (!this.initialized) {
|
||||
throw new Error("SkillManager not initialized");
|
||||
}
|
||||
|
||||
// Validate skillId to prevent path traversal
|
||||
if (
|
||||
!skillId ||
|
||||
skillId.includes("/") ||
|
||||
skillId.includes("\\") ||
|
||||
skillId.includes("..")
|
||||
) {
|
||||
throw new Error(`Invalid skill ID: ${skillId}`);
|
||||
}
|
||||
|
||||
try {
|
||||
// Get current metadata
|
||||
const currentMetadata = await skillStorage.getSkillMetadata(skillId);
|
||||
if (!currentMetadata) {
|
||||
throw new Error(`Skill not found: ${skillId}`);
|
||||
}
|
||||
|
||||
// Read the SKILL.md content from ZenFS
|
||||
const skillPath = zenfs.getSkillPath(skillId);
|
||||
const skillMdPath = `${skillPath}/SKILL.md`;
|
||||
|
||||
const skillMdExists = await zenfs.exists(skillMdPath);
|
||||
if (!skillMdExists) {
|
||||
throw new Error(`SKILL.md not found for skill: ${skillId}`);
|
||||
}
|
||||
|
||||
const skillMdContent = (await zenfs.readFile(
|
||||
skillMdPath,
|
||||
"utf8",
|
||||
)) as string;
|
||||
|
||||
// Parse the frontmatter to extract description and version
|
||||
const parsedMetadata = skillRegistry.parseSkillMetadata(skillMdContent);
|
||||
|
||||
// Check that name hasn't changed (we don't support rename)
|
||||
if (parsedMetadata.name && parsedMetadata.name !== skillId) {
|
||||
throw new Error(
|
||||
`Skill name mismatch: expected "${skillId}" but found "${parsedMetadata.name}" in SKILL.md. Skill renaming is not supported.`,
|
||||
);
|
||||
}
|
||||
|
||||
// Build updates object (only update fields that are present in frontmatter)
|
||||
const updates: Partial<SkillMetadata> = {};
|
||||
if (parsedMetadata.description !== undefined) {
|
||||
updates.description = parsedMetadata.description;
|
||||
}
|
||||
if (parsedMetadata.version !== undefined) {
|
||||
updates.version = parsedMetadata.version;
|
||||
}
|
||||
|
||||
// Update in IndexedDB if there are changes
|
||||
if (Object.keys(updates).length > 0) {
|
||||
await skillStorage.updateSkill(skillId, updates);
|
||||
}
|
||||
|
||||
// Get the updated metadata
|
||||
const updatedMetadata = await skillStorage.getSkillMetadata(skillId);
|
||||
if (!updatedMetadata) {
|
||||
throw new Error(
|
||||
`Failed to retrieve updated metadata for skill: ${skillId}`,
|
||||
);
|
||||
}
|
||||
|
||||
// Update the registry with updated metadata and refreshed content
|
||||
const existingSkill = skillRegistry.getSkill(currentMetadata.name);
|
||||
if (existingSkill) {
|
||||
skillRegistry.updateSkill(currentMetadata.name, {
|
||||
metadata: updatedMetadata,
|
||||
skillMdContent: skillMdContent,
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`✅ Skill metadata refreshed: ${skillId}`);
|
||||
|
||||
// Emit an event so UI components can react
|
||||
this._emit("skill_loaded", {
|
||||
type: "skill_metadata_refreshed",
|
||||
skillId,
|
||||
skillName: currentMetadata.name,
|
||||
skillMetadata: updatedMetadata,
|
||||
});
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`❌ Failed to refresh skill metadata for ${skillId}:`,
|
||||
error,
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
|
||||
getRegisteredTools(): any[] {
|
||||
return skillExecutor.getRegisteredTools();
|
||||
}
|
||||
|
||||
@@ -24,14 +24,13 @@ import {
|
||||
getAllTabsTool,
|
||||
getCurrentTabTool,
|
||||
getTabInfoTool,
|
||||
organizeTabsTool,
|
||||
ungroupTabsTool,
|
||||
} from "./tab";
|
||||
import { downloadChatImagesTool, downloadImageTool } from "./tools/downloads";
|
||||
|
||||
/**
|
||||
* All browser tools registered for AI use
|
||||
* Total: 32 tools (28 core + 4 intervention tools)
|
||||
* Total: 31 tools (27 core + 4 intervention tools)
|
||||
*
|
||||
* Disabled tools (per aipex):
|
||||
* - switch_to_tab (causes context switching issues)
|
||||
@@ -40,6 +39,7 @@ import { downloadChatImagesTool, downloadImageTool } from "./tools/downloads";
|
||||
* - capture_screenshot_to_clipboard (not enabled in aipex)
|
||||
* - download_text_as_markdown (not enabled in aipex)
|
||||
* - download_current_chat_images (architecture issue, not enabled in aipex)
|
||||
* - organize_tabs (stub implementation, temporarily disabled until AI grouping is complete)
|
||||
*/
|
||||
type BrowserFunctionTool = FunctionTool<
|
||||
unknown,
|
||||
@@ -48,13 +48,13 @@ type BrowserFunctionTool = FunctionTool<
|
||||
>;
|
||||
|
||||
const browserFunctionTools: BrowserFunctionTool[] = [
|
||||
// Browser/Tab Management (7 tools)
|
||||
// Browser/Tab Management (6 tools)
|
||||
// Note: organize_tabs temporarily disabled (stub/not shipped)
|
||||
getAllTabsTool,
|
||||
getCurrentTabTool,
|
||||
createNewTabTool,
|
||||
getTabInfoTool,
|
||||
closeTabTool,
|
||||
organizeTabsTool,
|
||||
ungroupTabsTool,
|
||||
|
||||
// UI Operations (7 tools) - computer tool replaces visual XY tools
|
||||
|
||||
@@ -135,8 +135,14 @@ export async function deleteTabGroup(groupId: number): Promise<{
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Tool to remove all tab groups in the current window.
|
||||
* Note: This tool uses the name "ungroup_tabs" for consistency with legacy naming.
|
||||
* Do not register this alongside the default ungroupTabsTool from ./tab.ts to avoid
|
||||
* duplicate tool name registration.
|
||||
*/
|
||||
export const ungroupAllTabsTool = tool({
|
||||
name: "ungroup_all_tabs",
|
||||
name: "ungroup_tabs",
|
||||
description: "Remove all tab groups in the current window",
|
||||
parameters: z.object({}),
|
||||
execute: async () => {
|
||||
|
||||
Reference in New Issue
Block a user