Skip to content

feat: Reconstructed the overall skill set and add web-skills implementation#323

Merged
zzcr merged 17 commits intodevfrom
zzc/refactor-skills-0210
Feb 13, 2026
Merged

feat: Reconstructed the overall skill set and add web-skills implementation#323
zzcr merged 17 commits intodevfrom
zzc/refactor-skills-0210

Conversation

@zzcr
Copy link
Member

@zzcr zzcr commented Feb 11, 2026

feat: 重构整体的skills技能方案,删除@专家的功能,改为web-skills渐进式披露方式

Pull Request (OpenTiny NEXT-SDKs)

PR Checklist

Please check if your PR fulfills the following requirements:

  • The commit message follows our Commit Message Guidelines
  • Tests for the changes have been added (for bug fixes / features)
  • Docs have been added / updated (for bug fixes / features)

PR Type

What kind of change does this PR introduce?

  • Bugfix
  • Feature
  • Code style update (formatting, local variables)
  • Refactoring (no functional changes, no api changes)
  • Build-related changes
  • CI-related changes
  • Documentation-related changes
  • Other... Please describe:

What is the current behavior?

Issue Number: N/A

What is the new behavior?

Does this PR introduce a breaking change?

  • Yes
  • No

Other information

Summary by CodeRabbit

  • New Features

    • Standardized SKILL.md protocol for defining skills; skills can be provided as markdown modules and auto-detected.
    • New skill tooling and product-guide skill content available.
  • Bug Fixes & Improvements

    • Components updated to accept skills as a markdown map (Record<string,string]); simplified skill loading and MCP server configuration.
    • Improved auto-import/resolver support for UI components.
  • Documentation

    • Reworked AI extension guide to center on SKILL.md, with examples, validation, and hot-update guidance.

@coderabbitai
Copy link

coderabbitai bot commented Feb 11, 2026

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Standardizes skills around SKILL.md (YAML front matter + Markdown body), replaces JS/TS skill modules with raw Markdown aggregation (import.meta.glob), adds next-sdk skill utilities and MCP server wiring, and refactors composables/components to consume skillMdModules and new MCP server APIs.

Changes

Cohort / File(s) Summary
Docs / Guides
docs/guide/ai-extension-skills.md, docs/guide/tiny-robot-remoter.md
Rewritten to center on SKILL.md format, import.meta.glob usage, new skills prop shape (Record<string,string>), MCP server presets, and updated examples.
Skill Markdown additions
packages/doc-ai/src/skills/calculator/SKILL.md, packages/doc-ai/src/skills/product-guide/SKILL.md, packages/doc-ai/src/skills/product-guide/reference/product-shangjia.md, packages/next-wxt/skills/drawer-expert/SKILL.md, packages/next-wxt/skills/month-report-expert/SKILL.md
Added SKILL.md documents (YAML front matter + content) representing skills and references.
Skill aggregation exports
packages/doc-ai/src/skills/index.ts, packages/next-wxt/skills/index.ts, packages/next-wxt/skills/.../*.md
Removed prior JS/TS skill loaders/getters; added skillMdModules export via import.meta.glob('./**/*.md', { query: '?raw', import: 'default', eager: true }).
next-sdk skill utilities
packages/next-sdk/skills/index.ts, packages/next-sdk/index.ts
New public utilities: front-matter parsing, skill discovery, overviews, system-prompt formatting, MD accessors, and createSkillTools (get_skill_content). Exports/types added.
Composable refactor
packages/next-remoter/src/composable/useSkill.ts
Refactored useSkillWithTools to options object API; returns processSkillMentions, skillPromptPart, skillTools, skillOverviews; data-driven (no mention UI).
Component props & wiring
packages/next-remoter/src/components/TinyRobotChat.vue, packages/doc-ai/src/App.vue, packages/next-wxt/entrypoints/sidepanel/App.vue
Changed skills prop to Record<string,string>, added mcpServers prop, removed sessionId/transport plumbing in favor of createMcpServer and raw MD modules; TinyRemoter now receives skillMdModules.
MCP server modules
packages/doc-ai/src/mcp-servers/index.ts, packages/doc-ai/src/mcp-servers/product-guide/tools.ts, packages/next-wxt/mcp-servers/excalidraw.com/meta.ts
Added MCP server wiring, exported clientTransport and createMcpServer, registered a product-guide tool, and set Excalidraw server isAlwaysEnabled: true.
Removed legacy skill code & types
packages/next-wxt/skills/*.ts, packages/next-wxt/skills/utils/*, packages/next-wxt/skills/skillManager.ts, packages/next-wxt/skills/types.d.ts
Deleted legacy skill meta/prompt/tools modules, skillManager utilities, domain-tool resolution helpers, and related type definitions (many exports removed).
doc-ai app wiring & build config
packages/doc-ai/src/App.vue, packages/doc-ai/src/skills/index.ts, packages/doc-ai/vite.config.ts, packages/doc-ai/package.json, packages/next-remoter/src/composable/CustomAgentModelProvider.ts
App.vue now supplies skillMdModules and mcpServers to TinyRemoter; Vite config and package.json add Vant resolver; provider baseURL shortened.

Sequence Diagram(s)

sequenceDiagram
  participant Build as Vite Build
  participant SkillMd as Skill MD modules
  participant App as App / TinyRemoter
  participant Composable as useSkillWithTools
  participant SDK as next-sdk (createSkillTools)
  participant MCP as MCP Server (createMcpServer)
  Build->>SkillMd: import.meta.glob(...) eager -> skillMdModules
  SkillMd->>App: pass skillMdModules prop
  App->>MCP: onMounted -> createMcpServer()
  App->>Composable: init useSkillWithTools({ skillsRef: skillMdModules, systemPrompt, agent })
  Composable->>SDK: getSkillOverviews / formatSkillsForSystemPrompt / createSkillTools
  SDK-->>Composable: skillPromptPart, skillTools (includes get_skill_content)
  TinyRobot->>MCP: tool call -> get_skill_content(path|name)
  MCP->>SkillMd: fetch requested MD content
  SkillMd-->>MCP: return MD content
  MCP-->>TinyRobot: tool result (content/path)
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Poem

🐇 I hopped through folders, found YAML delight,
SKILL.md lined up, all tidy and bright.
One file to rule prompts, tools, and lore,
No scattered modules, less cluttered floor.
Hooray — the rabbit stamps a tiny bite! 🥕

🚥 Pre-merge checks | ✅ 3 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Merge Conflict Detection ⚠️ Warning ❌ Merge conflicts detected (13 files):

⚔️ .github/workflows/deploy-obs-playground.yml (content)
⚔️ docs/guide/ai-extension-skills.md (content)
⚔️ docs/guide/tiny-robot-remoter.md (content)
⚔️ packages/doc-ai/package.json (content)
⚔️ packages/doc-ai/src/App.vue (content)
⚔️ packages/doc-ai/vite.config.ts (content)
⚔️ packages/next-remoter/src/components/TinyRobotChat.vue (content)
⚔️ packages/next-remoter/src/composable/CustomAgentModelProvider.ts (content)
⚔️ packages/next-remoter/src/composable/useSkill.ts (content)
⚔️ packages/next-sdk/index.ts (content)
⚔️ packages/next-wxt/entrypoints/sidepanel/App.vue (content)
⚔️ packages/next-wxt/mcp-servers/excalidraw.com/meta.ts (content)
⚔️ packages/next-wxt/skills/index.ts (content)

These conflicts must be resolved before merging into dev.
Resolve conflicts locally and push changes to this branch.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: reconstructing the overall skill set and implementing web-skills functionality, which aligns with the extensive refactoring of skill definitions, removal of old skill modules, and introduction of the SKILL.md standardization.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch zzc/refactor-skills-0210

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🤖 Fix all issues with AI agents
In `@packages/doc-ai/src/skills/calculator/SKILL.md`:
- Around line 12-14: Fix the duplicated/unclear parameter descriptions for `a`,
`b`, and `operation` in SKILL.md: replace "商品数量 当前商品数量" with a single clear
description like "商品数量(当前商品数量)" or simply "商品数量", replace "商品库存 商品库存" with
"商品库存", and simplify `operation` to "运算类型(加、减、乘、除)" so each parameter line is
concise and non-redundant.

In `@packages/doc-ai/src/skills/product-guide/SKILL.md`:
- Line 12: Update the relative reference in SKILL.md so get_skill_content can
find the file: change the path string './reference/product-shangjia.md' in
packages/doc-ai/src/skills/product-guide/SKILL.md to the full skills-root
relative path './product-guide/reference/product-shangjia.md' so that the
modules lookup used by get_skill_content(modules, path) matches the key stored
in the import.meta.glob('?raw') map.

In `@packages/next-remoter/src/composable/useSkill.ts`:
- Around line 44-45: The code reads customAgentProvider.llmConfig?.extraTools
but then assigns to customAgentProvider.llmConfig.extraTools unguarded, causing
a TypeError if llmConfig is nullish; update the logic around symbols
customAgentProvider, llmConfig, extraTools and skillTools.value so llmConfig is
guaranteed to exist before assignment (e.g., if llmConfig is null/undefined,
initialize it to an object) and then merge extraTools safely (use the existing
extra from llmConfig or {} and set llmConfig.extraTools = { ...extra,
...skillTools.value }).
- Around line 39-45: The code reads computed reactive values
(skillPromptPart.value and skillTools.value) once and assigns them into
customAgentProvider, so later updates to skillsRef won't propagate; change this
by wrapping the assignments in a reactive watcher (e.g., watchEffect or watch)
that updates customAgentProvider.systemPrompt (combining systemPrompt and
skillPromptPart.value) and customAgentProvider.llmConfig.extraTools (merging
existing extra with skillTools.value) whenever skillPromptPart or skillTools
change, keeping references to customAgentProvider, systemPrompt,
skillPromptPart, skillTools, and llmConfig in the watcher closure.

In `@packages/next-sdk/skills/index.ts`:
- Around line 109-141: The module docs mention a list_skills tool but
createSkillTools only returns get_skill_content; either re-add list_skills or
remove/update the stale comments. If you want the tool, implement a new tool
inside createSkillTools named list_skills that returns the array of skill
overviews (name/description) derived from modules (e.g., by reusing the logic in
formatSkillsForSystemPrompt or by scanning modules keys and reading SKILL.md via
getSkillMdContent/getMainSkillPathByName), and include it in the returned
SkillToolsSet as list_skills; otherwise update the docstring and any references
to remove mention of list_skills so comments match the implementation.

In `@packages/next-wxt/skills/drawer-expert/SKILL.md`:
- Line 88: Fix the typo in the SKILL.md text: replace the incorrect fragment
"必须)" with "(必须)" so the opening parenthesis is restored; locate the sentence
containing "调用updateElement,更新形状元素,添加boundElements属性,其值为一个数组,包含指向文本元素的引用" and
update that occurrence accordingly.
🧹 Nitpick comments (9)
packages/next-remoter/src/composable/CustomAgentModelProvider.ts (1)

99-109: Fragile /prompt path manipulation.

baseURL.includes('/prompt') and baseURL.replace('/prompt', '') match any occurrence of /prompt in the URL, not just the suffix. If a future baseURL contains /prompt elsewhere in the path, this logic would break. Consider using endsWith/suffix-based checks instead.

Suggested improvement
-      if (!baseURL.includes('/prompt')) {
-        baseURL = baseURL + '/prompt'
+      if (!baseURL.endsWith('/prompt')) {
+        baseURL = baseURL + '/prompt'
       }
     } else {
       // 如果关闭了生成式UI,移除 '/prompt' 后缀
-      baseURL = baseURL.replace('/prompt', '')
+      if (baseURL.endsWith('/prompt')) {
+        baseURL = baseURL.slice(0, -'/prompt'.length)
+      }
packages/next-wxt/skills/drawer-expert/SKILL.md (1)

139-178: JSON examples contain invalid JavaScript-style comments.

The binding example (lines 168–170) uses // comments inside JSON blocks. While this is a Markdown prompt for an LLM and may work in practice, invalid JSON in examples could confuse the model or lead to malformed output. Consider removing the comments or placing them outside the JSON block.

packages/next-wxt/entrypoints/sidepanel/App.vue (1)

233-238: Dead code: button with v-if="false" will never render.

This button and its associated styles (.record-button, .record-button__icon, .record-button:hover) are unreachable. Consider removing both the template block and the unused CSS, or leaving a comment explaining why it's kept (e.g., feature flag placeholder).

packages/next-remoter/src/components/TinyRobotChat.vue (1)

338-345: processSkillMentions naming is now misleading — no @-mention processing remains.

The function name processSkillMentions implies @-mention handling, but the refactor removed that behavior. Consider renaming to something like processSkills or prepareSkillContext to better reflect its current role.

packages/next-sdk/skills/index.ts (3)

29-43: Regex-based YAML front matter parser won't handle quoted values.

parseSkillFrontMatter extracts values via /^name:\s*(.+)$/m, which captures the entire remainder of the line including quotes. For name: "my skill", it returns "my skill" (with quotes). If skill documents might use quoted YAML values, consider stripping surrounding quotes. For now this is fine if you control all SKILL.md authoring.

Optional: strip surrounding quotes
   const name = nameMatch?.[1]?.trim()
   const description = descMatch?.[1]?.trim()
+  const unquote = (s?: string) => s?.replace(/^(['"])(.*)\1$/, '$2')
 
-  return name && description ? { name, description } : null
+  return name && description ? { name: unquote(name)!, description: unquote(description)! } : null

96-101: Prefer strict equality over startsWith for path matching.

getMainSkillPathByName uses startsWith to match ./name/SKILL.md, but since all main skill paths follow the exact ./X/SKILL.md pattern, === is the correct semantic and avoids any edge-case ambiguity.

Proposed fix
 export function getMainSkillPathByName(modules: Record<string, string>, name: string): string | undefined {
-  return getMainSkillPaths(modules).find((p) => p.startsWith(`./${name}/SKILL.md`))
+  return getMainSkillPaths(modules).find((p) => p === `./${name}/SKILL.md`)
 }

115-137: Both skillName and path are optional — no input validation for the case when neither is provided.

When the LLM calls get_skill_content with {} (both fields omitted), the tool silently returns an error object. Consider adding a Zod refine to require at least one field, which gives better error messages at the schema validation layer.

Proposed fix
     inputSchema: z.object({
       skillName: z.string().optional().describe('技能名称,与目录名一致,如 calculator'),
       path: z.string().optional().describe('文档相对路径,如 ./calculator/SKILL.md 或 ./product-guide/reference/xxx.md')
-    }),
+    }).refine(
+      (data) => data.skillName || data.path,
+      { message: '至少需要提供 skillName 或 path 其中一个参数' }
+    ),
packages/next-remoter/src/composable/useSkill.ts (2)

4-13: agent and customAgentProvider are typed as any; agent is unused.

  1. Both agent (Line 10) and customAgentProvider (Line 12) use any, which defeats TypeScript's type safety. Consider defining or importing proper interface types for these.
  2. agent is declared in the options interface but never destructured or referenced in useSkillWithTools (Line 20 only pulls skillsRef, systemPrompt, customAgentProvider). If it's no longer needed, remove it to avoid a misleading API surface.
Proposed fix (remove unused property, add TODO for proper typing)
 export interface UseSkillWithToolsOptions {
   /** 用户层传入的 skill .md 模块(key 路径,value 内容),由 next-sdk 处理;大模型通过 list_skills / get_skill_content 自动识别并加载技能 */
   skillsRef?: Ref<Record<string, string> | undefined>
   /** 基础系统提示词 */
   systemPrompt: string
-  /** CustomAgentModelProvider 的 agent 实例 */
-  agent: any
-  /** CustomAgentModelProvider 实例,用于写 systemPrompt、合并 extraTools */
-  customAgentProvider: any
+  /** CustomAgentModelProvider 实例,用于写 systemPrompt、合并 extraTools */
+  // TODO: replace `any` with the actual CustomAgentModelProvider type
+  customAgentProvider: any
 }

As per coding guidelines, "All code must be TypeScript with strict typing".


47-50: Consider a more descriptive element type for skillItems if this stub will be extended.

never[] is technically precise for a permanently empty array, but it prevents consumers from typing any future use of skillItems. If this is a temporary placeholder that may later carry items, consider using a named type (e.g., SkillMeta[] or a dedicated SkillItem[]) to keep the return contract forward-compatible.

@zzcr zzcr changed the title feat: Reconstructed the overall skill set feat: Reconstructed the overall skill set and add web-skills implementation Feb 13, 2026
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@packages/doc-ai/src/App.vue`:
- Line 8: The tiny-remoter component is using one-way binding (:show="show") so
it cannot emit update:show to update parent state; change the binding on the
TinyRemoter/TinyRobotChat usage from :show="show" to v-model:show="show" so the
component's defineModel('show') / emit('update:show') will update the parent's
show reactive variable; keep the other props (skillMdModules, menuItems,
mcpServers) as-is and remove the old :show binding to avoid duplicate bindings.

In `@packages/next-remoter/src/components/TinyRobotChat.vue`:
- Around line 274-281: The prop declaration for skills in TinyRobotChat.vue was
changed to Record<string,string>, which is a breaking change for callers that
pass an array of MentionItem[]; update the component to accept both shapes and
normalize them internally: restore the prop validator/type to allow Array or
Object (keep the prop name skills), provide a default of undefined, and add a
small normalization step (e.g., normalizeSkills or inline logic where skills are
used) that detects an Array<MentionItem> vs Record<string,string> and converts
arrays into the expected Record shape before downstream use; this preserves
backwards compatibility while keeping the new Record format supported.
🧹 Nitpick comments (5)
packages/doc-ai/src/mcp-servers/product-guide/tools.ts (1)

3-18: Stub handler returns placeholder text — is this intentional?

The tool handler just echoes back 产品指南${productId} without any real product-guide logic. If this is a temporary scaffold, consider adding a // TODO comment so it doesn't get forgotten.

packages/doc-ai/src/mcp-servers/index.ts (1)

1-2: Minor: consolidate imports from the same module.

Both imports come from @opentiny/next-sdk.

Proposed fix
-import { WebMcpServer } from '@opentiny/next-sdk'
-import { createMessageChannelPairTransport } from '@opentiny/next-sdk'
+import { WebMcpServer, createMessageChannelPairTransport } from '@opentiny/next-sdk'
docs/guide/tiny-robot-remoter.md (1)

314-326: mcpServers example: type string value should match documented options.

The example uses type: 'streamableHttp' (line 318) and type: 'local' (line 322), which matches the documented types on lines 330-332. Looks good.

One minor note: the clientTransport variable in the example (line 323) is used without showing its import/creation. Consider adding a brief comment or import hint so readers know where it comes from.

packages/next-remoter/src/components/TinyRobotChat.vue (1)

540-544: Sequential await in for...of loop serializes MCP server loading.

If multiple MCP servers are configured, they'll be loaded one at a time. This is acceptable for a small number of servers, but consider Promise.all if parallel initialization is safe.

Parallel loading alternative
   if (props.mcpServers) {
-    for (const [name, config] of Object.entries(props.mcpServers)) {
-      await loadMcpServerToPlugin(name, config)
-    }
+    await Promise.all(
+      Object.entries(props.mcpServers).map(([name, config]) => loadMcpServerToPlugin(name, config))
+    )
   }
packages/doc-ai/src/App.vue (1)

22-27: Add as const or type annotation to ensure type: 'local' is narrowed.

Without a type annotation, TypeScript infers type as string rather than the literal 'local', which may not satisfy a discriminated union in McpServerConfig.

Proposed fix
+import type { McpServerConfig } from '@opentiny/next-sdk'
+
 // 业界格式:key 为 MCP 服务器名称,value 为 McpServerConfig
-const mcpServers = {
+const mcpServers: Record<string, McpServerConfig> = {
   'local-mcp-server': {
     type: 'local',
     transport: clientTransport
   }
 }

Comment on lines 274 to 281
/**
* 用户层传入的 skill .md 模块(Vite import.meta.glob 等得到的 Record<path, content>),
* 由 remoter 调用 next-sdk 的 skill 能力处理:生成 systemPrompt 技能说明、内置 list_skills / get_skill_content 工具,大模型可自动识别并加载技能
*/
skills: {
type: Object as () => MentionItem[],
default: () => []
type: Object as () => Record<string, string>,
default: undefined
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Breaking change: skills prop type changed from array to Record<string, string>.

This is a breaking API change — existing consumers passing an array of MentionItem[] will silently receive incorrect behavior (no type error at runtime in JS templates). Ensure this is communicated in release notes or a migration guide.

🤖 Prompt for AI Agents
In `@packages/next-remoter/src/components/TinyRobotChat.vue` around lines 274 -
281, The prop declaration for skills in TinyRobotChat.vue was changed to
Record<string,string>, which is a breaking change for callers that pass an array
of MentionItem[]; update the component to accept both shapes and normalize them
internally: restore the prop validator/type to allow Array or Object (keep the
prop name skills), provide a default of undefined, and add a small normalization
step (e.g., normalizeSkills or inline logic where skills are used) that detects
an Array<MentionItem> vs Record<string,string> and converts arrays into the
expected Record shape before downstream use; this preserves backwards
compatibility while keeping the new Record format supported.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Fix all issues with AI agents
In `@packages/next-remoter/src/composable/useSkill.ts`:
- Around line 4-13: Remove the unused agent field from the
UseSkillWithToolsOptions interface since useSkillWithTools only destructures
skillsRef, systemPrompt, and customAgentProvider; update the interface
declaration by deleting the "agent: any" property (symbol:
UseSkillWithToolsOptions) and then run a quick search for any external
references to UseSkillWithToolsOptions to update call sites or tests if they
relied on agent to avoid type errors; ensure TypeScript compiles after the
change.

In `@packages/next-wxt/skills/drawer-expert/SKILL.md`:
- Line 229: 在第 3 条标题 "箭头/连线必须绑定元素" 中将口语词 "俩俩" 替换为正式用语;建议直接改为 "两两双向链接" 或更简洁地改为
"双向链接"(保留示例 "eleA arrow eleB" 以示意关系),确保句子流畅且与文档风格一致。
- Line 38: The sentence in SKILL.md that explains using
ExcalidrawElementSkeleton currently has an incorrect Chinese punctuation mark
before "等"; remove the enumerative comma/pause "、" before "等" so the phrase
reads "...随机种子等属性" (no preceding "、"), updating the sentence that mentions
ExcalidrawElementSkeleton and ExcalidrawElement accordingly to ensure correct
Chinese grammar and punctuation.
🧹 Nitpick comments (2)
packages/next-sdk/skills/index.ts (1)

96-101: getMainSkillPathByName uses .startsWith where strict equality would be more precise.

Since MAIN_SKILL_PATH_REG guarantees paths match exactly ./name/SKILL.md, startsWith is functionally equivalent to === here but could match unintended prefixes in theory (e.g., if module keys changed format). Consider using === for clarity.

 export function getMainSkillPathByName(modules: Record<string, string>, name: string): string | undefined {
-  return getMainSkillPaths(modules).find((p) => p.startsWith(`./${name}/SKILL.md`))
+  return getMainSkillPaths(modules).find((p) => p === `./${name}/SKILL.md`)
 }
packages/next-remoter/src/composable/useSkill.ts (1)

22-37: Skill tool objects are recreated on every skillsRef change — acceptable but worth noting.

createSkillTools (line 36) builds a new tool() instance on each reactive update. For typical usage this is fine, but if skillsRef changes frequently, this creates unnecessary allocations. If this becomes a concern, memoizing by module identity could help.

Comment on lines 4 to 13
export interface UseSkillWithToolsOptions {
/** 用户层传入的 skill .md 模块(key 路径,value 内容),由 next-sdk 处理;大模型通过 get_skill_content 自动识别并加载技能 */
skillsRef?: Ref<Record<string, string> | undefined>
/** 基础系统提示词 */
systemPrompt: string
/** CustomAgentModelProvider 的 agent 实例 */
agent: any
/** CustomAgentModelProvider 实例,用于写 systemPrompt、合并 extraTools */
customAgentProvider: any
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

# First, let's examine the file structure and get the full context
cat -n packages/next-remoter/src/composable/useSkill.ts | head -50

Repository: opentiny/next-sdk

Length of output: 2204


🏁 Script executed:

# Search for how agent is used in this file
rg -n 'agent' packages/next-remoter/src/composable/useSkill.ts -B2 -A2

Repository: opentiny/next-sdk

Length of output: 268


🏁 Script executed:

# Check how useSkillWithTools is called and if agent is passed
rg -nC5 'useSkillWithTools' --type=ts --type=vue

Repository: opentiny/next-sdk

Length of output: 88


🏁 Script executed:

# Search for files that import or use useSkillWithTools
rg -l 'useSkillWithTools' --type ts

Repository: opentiny/next-sdk

Length of output: 109


🏁 Script executed:

# Check if UseSkillWithToolsOptions is imported elsewhere
rg -l 'UseSkillWithToolsOptions' --type ts

Repository: opentiny/next-sdk

Length of output: 109


🏁 Script executed:

# Search for useSkillWithTools calls to see what parameters are passed
rg -B2 -A2 'useSkillWithTools\(' --type ts

Repository: opentiny/next-sdk

Length of output: 524


Remove unused agent field from UseSkillWithToolsOptions interface.

The agent property is declared in the interface but never destructured or referenced in the useSkillWithTools function (line 20 only destructures skillsRef, systemPrompt, and customAgentProvider). Removing it eliminates unnecessary interface bloat.

Proposed fix
 export interface UseSkillWithToolsOptions {
   skillsRef?: Ref<Record<string, string> | undefined>
   systemPrompt: string
-  agent: any
   customAgentProvider: any
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export interface UseSkillWithToolsOptions {
/** 用户层传入的 skill .md 模块(key 路径,value 内容),由 next-sdk 处理;大模型通过 get_skill_content 自动识别并加载技能 */
skillsRef?: Ref<Record<string, string> | undefined>
/** 基础系统提示词 */
systemPrompt: string
/** CustomAgentModelProvider 的 agent 实例 */
agent: any
/** CustomAgentModelProvider 实例,用于写 systemPrompt、合并 extraTools */
customAgentProvider: any
}
export interface UseSkillWithToolsOptions {
/** 用户层传入的 skill .md 模块(key 路径,value 内容),由 next-sdk 处理;大模型通过 get_skill_content 自动识别并加载技能 */
skillsRef?: Ref<Record<string, string> | undefined>
/** 基础系统提示词 */
systemPrompt: string
/** CustomAgentModelProvider 实例,用于写 systemPrompt、合并 extraTools */
customAgentProvider: any
}
🤖 Prompt for AI Agents
In `@packages/next-remoter/src/composable/useSkill.ts` around lines 4 - 13, Remove
the unused agent field from the UseSkillWithToolsOptions interface since
useSkillWithTools only destructures skillsRef, systemPrompt, and
customAgentProvider; update the interface declaration by deleting the "agent:
any" property (symbol: UseSkillWithToolsOptions) and then run a quick search for
any external references to UseSkillWithToolsOptions to update call sites or
tests if they relied on agent to avoid type errors; ensure TypeScript compiles
after the change.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix punctuation: remove comma before "等".

In Chinese grammar, "等" should not be preceded by "、" when used at the end of a list.

📝 Proposed fix
-**重要理念**: 你将通过创建**元素骨架 (`ExcalidrawElementSkeleton`)** 对象来添加元素,而非手动构建完整的 `ExcalidrawElement`。`ExcalidrawElementSkeleton` 是一个简化的、专为编程创建而设计的对象。Excalidraw前端会自动补全版本号、随机种子、等属性。
+**重要理念**: 你将通过创建**元素骨架 (`ExcalidrawElementSkeleton`)** 对象来添加元素,而非手动构建完整的 `ExcalidrawElement`。`ExcalidrawElementSkeleton` 是一个简化的、专为编程创建而设计的对象。Excalidraw前端会自动补全版本号、随机种子等属性。
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
**重要理念**: 你将通过创建**元素骨架 (`ExcalidrawElementSkeleton`)** 对象来添加元素,而非手动构建完整的 `ExcalidrawElement``ExcalidrawElementSkeleton` 是一个简化的、专为编程创建而设计的对象。Excalidraw前端会自动补全版本号、随机种子、等属性
**重要理念**: 你将通过创建**元素骨架 (`ExcalidrawElementSkeleton`)** 对象来添加元素,而非手动构建完整的 `ExcalidrawElement``ExcalidrawElementSkeleton` 是一个简化的、专为编程创建而设计的对象。Excalidraw前端会自动补全版本号、随机种子等属性
🧰 Tools
🪛 LanguageTool

[uncategorized] ~38-~38: 您的意思是“"不"全”?
Context: ...ton` 是一个简化的、专为编程创建而设计的对象。Excalidraw前端会自动补全版本号、随机种子、等属性。 ### A. 通用核心属性 (所有元素骨架都包含...

(BU)

🤖 Prompt for AI Agents
In `@packages/next-wxt/skills/drawer-expert/SKILL.md` at line 38, The sentence in
SKILL.md that explains using ExcalidrawElementSkeleton currently has an
incorrect Chinese punctuation mark before "等"; remove the enumerative
comma/pause "、" before "等" so the phrase reads "...随机种子等属性" (no preceding "、"),
updating the sentence that mentions ExcalidrawElementSkeleton and
ExcalidrawElement accordingly to ensure correct Chinese grammar and punctuation.

Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Improve wording: replace "俩俩" with standard Chinese.

"俩俩" is colloquial. Use "两两" (pairwise) for formal documentation, or simplify to just "双向链接" since "必须" already conveys the requirement.

📝 Proposed fixes

Option 1 (recommended - simpler):

-3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须俩俩双向链接
+3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须双向链接

Option 2 (more formal):

-3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须俩俩双向链接
+3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须两两双向链接
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须俩俩双向链接
3. **箭头/连线必须绑定元素** 箭头或连线必须双向链接到对应的元素上,比如eleA arrow eleB,必须双向链接
🤖 Prompt for AI Agents
In `@packages/next-wxt/skills/drawer-expert/SKILL.md` at line 229, 在第 3 条标题
"箭头/连线必须绑定元素" 中将口语词 "俩俩" 替换为正式用语;建议直接改为 "两两双向链接" 或更简洁地改为 "双向链接"(保留示例 "eleA arrow
eleB" 以示意关系),确保句子流畅且与文档风格一致。

@zzcr zzcr merged commit fa56d9e into dev Feb 13, 2026
2 checks passed
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.

1 participant

Comments