@yeaft/webchat-agent 1.0.645 → 1.0.647

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@yeaft/webchat-agent",
3
- "version": "1.0.645",
3
+ "version": "1.0.647",
4
4
  "description": "Remote worker agent for Yeaft Web Code Agent — connects the native Yeaft engine, CLI providers, and workbench tools",
5
5
  "main": "index.js",
6
6
  "type": "module",
package/yeaft/plugins.js CHANGED
@@ -124,6 +124,47 @@ export function createPluginSkillManager(skillManager, plugins) {
124
124
  };
125
125
  }
126
126
 
127
+ const PLUGIN_SKILL_CONTENT_MAX_BYTES = 256 * 1024;
128
+
129
+ /**
130
+ * Read one effective layered Skill from the full catalog manager, independently
131
+ * of inference allowlists. Only the body and linked filenames belong to this
132
+ * browser projection; never pass a linked file path to SkillManager.view().
133
+ */
134
+ export function buildPluginSkillDetail({ skillManager } = {}, skillName) {
135
+ if (typeof skillName !== 'string' || !skillName.trim()
136
+ || skillName !== skillName.trim() || /[/\\\u0000-\u001f\u007f]/.test(skillName)
137
+ || skillName === '.' || skillName === '..') {
138
+ throw new Error('invalid skillName: expected a non-empty Skill name');
139
+ }
140
+ const viewed = skillManager?.view?.(skillName);
141
+ const skill = viewed?.skill;
142
+ if (!skill || skill.name !== skillName) throw new Error(`skill not found: ${skillName}`);
143
+
144
+ let content = typeof skill.content === 'string' ? skill.content : '';
145
+ const contentTruncated = Buffer.byteLength(content, 'utf8') > PLUGIN_SKILL_CONTENT_MAX_BYTES;
146
+ if (contentTruncated) {
147
+ const bytes = Buffer.from(content, 'utf8');
148
+ let end = PLUGIN_SKILL_CONTENT_MAX_BYTES;
149
+ // Do not decode an incomplete UTF-8 code point into a replacement character.
150
+ while ((bytes[end] & 0xc0) === 0x80) end--;
151
+ content = bytes.subarray(0, end).toString('utf8');
152
+ }
153
+ const strings = value => Array.isArray(value) ? value.filter(item => typeof item === 'string') : [];
154
+ return {
155
+ name: skillName,
156
+ description: typeof skill.description === 'string' ? skill.description : '',
157
+ trigger: typeof skill.trigger === 'string' ? skill.trigger : '',
158
+ keywords: strings(skill.keywords),
159
+ category: typeof skill.category === 'string' ? skill.category : null,
160
+ tier: typeof skill._tier === 'string' ? skill._tier : null,
161
+ content,
162
+ references: strings(viewed.references),
163
+ templates: strings(viewed.templates),
164
+ ...(contentTruncated ? { contentTruncated: true } : {}),
165
+ };
166
+ }
167
+
127
168
  /** Build a browser-safe catalog from already discovered Agent assets. */
128
169
  export function buildPluginCatalog({ toolRegistry, skillManager, mcpConfig, mcpManager } = {}) {
129
170
  const tools = typeof toolRegistry?.getAllTools === 'function'
@@ -32,7 +32,7 @@ import {
32
32
  removeManagedProjectSkill,
33
33
  removeManagedSkill,
34
34
  } from './skills.js';
35
- import { buildPluginCatalog, createPluginSkillManager, resolveMcpPluginPolicy } from './plugins.js';
35
+ import { buildPluginCatalog, buildPluginSkillDetail, createPluginSkillManager, resolveMcpPluginPolicy } from './plugins.js';
36
36
  import { MCPManager } from './mcp.js';
37
37
  import { sendToServer } from '../connection/buffer.js';
38
38
  import ctx from '../context.js';
@@ -3655,13 +3655,17 @@ export function __testLoadPluginCatalogMcpConfig(yeaftDir) {
3655
3655
  export function handleYeaftPluginCatalog(msg = {}) {
3656
3656
  const requestId = msg.requestId || null;
3657
3657
  const requestedWorkDir = normalizeSessionWorkDir(msg.workDir);
3658
+ const wantsSkillDetail = Object.prototype.hasOwnProperty.call(msg, 'skillName');
3658
3659
  try {
3659
- const catalog = buildPluginCatalog(resolvePluginCatalogRuntime(requestedWorkDir));
3660
+ const runtime = resolvePluginCatalogRuntime(requestedWorkDir);
3661
+ const skillDetail = wantsSkillDetail ? buildPluginSkillDetail(runtime, msg.skillName) : null;
3662
+ const catalog = buildPluginCatalog(runtime);
3660
3663
  sendToServer({
3661
3664
  type: 'yeaft_plugin_catalog_result',
3662
3665
  requestId,
3663
3666
  ...(msg._requestClientId ? { _requestClientId: msg._requestClientId } : {}),
3664
3667
  catalog,
3668
+ ...(wantsSkillDetail ? { skillDetail } : {}),
3665
3669
  error: null,
3666
3670
  });
3667
3671
  } catch (err) {
@@ -3670,6 +3674,7 @@ export function handleYeaftPluginCatalog(msg = {}) {
3670
3674
  requestId,
3671
3675
  ...(msg._requestClientId ? { _requestClientId: msg._requestClientId } : {}),
3672
3676
  catalog: { tools: [], skills: [], mcpServers: [] },
3677
+ ...(wantsSkillDetail ? { skillDetail: null } : {}),
3673
3678
  error: err?.message || String(err),
3674
3679
  });
3675
3680
  }