snow-ai 0.5.24 → 0.5.25

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/bundle/cli.mjs CHANGED
@@ -1429,11 +1429,11 @@ var require_react_development = __commonJS({
1429
1429
  var dispatcher = resolveDispatcher();
1430
1430
  return dispatcher.useReducer(reducer3, initialArg, init);
1431
1431
  }
1432
- function useRef13(initialValue) {
1432
+ function useRef14(initialValue) {
1433
1433
  var dispatcher = resolveDispatcher();
1434
1434
  return dispatcher.useRef(initialValue);
1435
1435
  }
1436
- function useEffect50(create3, deps) {
1436
+ function useEffect51(create3, deps) {
1437
1437
  var dispatcher = resolveDispatcher();
1438
1438
  return dispatcher.useEffect(create3, deps);
1439
1439
  }
@@ -2216,14 +2216,14 @@ var require_react_development = __commonJS({
2216
2216
  exports2.useContext = useContext13;
2217
2217
  exports2.useDebugValue = useDebugValue;
2218
2218
  exports2.useDeferredValue = useDeferredValue;
2219
- exports2.useEffect = useEffect50;
2219
+ exports2.useEffect = useEffect51;
2220
2220
  exports2.useId = useId;
2221
2221
  exports2.useImperativeHandle = useImperativeHandle2;
2222
2222
  exports2.useInsertionEffect = useInsertionEffect;
2223
2223
  exports2.useLayoutEffect = useLayoutEffect2;
2224
2224
  exports2.useMemo = useMemo30;
2225
2225
  exports2.useReducer = useReducer8;
2226
- exports2.useRef = useRef13;
2226
+ exports2.useRef = useRef14;
2227
2227
  exports2.useState = useState57;
2228
2228
  exports2.useSyncExternalStore = useSyncExternalStore;
2229
2229
  exports2.useTransition = useTransition;
@@ -45437,10 +45437,10 @@ var require_symlink = __commonJS({
45437
45437
  pathExists2(dstpath, (err, destinationExists) => {
45438
45438
  if (err) return callback(err);
45439
45439
  if (destinationExists) return callback(null);
45440
- symlinkPaths(srcpath, dstpath, (err2, relative8) => {
45440
+ symlinkPaths(srcpath, dstpath, (err2, relative9) => {
45441
45441
  if (err2) return callback(err2);
45442
- srcpath = relative8.toDst;
45443
- symlinkType(relative8.toCwd, type, (err3, type2) => {
45442
+ srcpath = relative9.toDst;
45443
+ symlinkType(relative9.toCwd, type, (err3, type2) => {
45444
45444
  if (err3) return callback(err3);
45445
45445
  const dir = path53.dirname(dstpath);
45446
45446
  pathExists2(dir, (err4, dirExists) => {
@@ -45458,9 +45458,9 @@ var require_symlink = __commonJS({
45458
45458
  function createSymlinkSync(srcpath, dstpath, type) {
45459
45459
  const destinationExists = fs42.existsSync(dstpath);
45460
45460
  if (destinationExists) return void 0;
45461
- const relative8 = symlinkPathsSync(srcpath, dstpath);
45462
- srcpath = relative8.toDst;
45463
- type = symlinkTypeSync(relative8.toCwd, type);
45461
+ const relative9 = symlinkPathsSync(srcpath, dstpath);
45462
+ srcpath = relative9.toDst;
45463
+ type = symlinkTypeSync(relative9.toCwd, type);
45464
45464
  const dir = path53.dirname(dstpath);
45465
45465
  const exists = fs42.existsSync(dir);
45466
45466
  if (exists) return fs42.symlinkSync(srcpath, dstpath, type);
@@ -45971,8 +45971,8 @@ var init_logger = __esm({
45971
45971
  const timestamp = Date.now();
45972
45972
  const ext = path5.extname(filePath);
45973
45973
  const basename6 = path5.basename(filePath, ext);
45974
- const dirname10 = path5.dirname(filePath);
45975
- const rotatedPath = path5.join(dirname10, `${basename6}-${timestamp}${ext}`);
45974
+ const dirname11 = path5.dirname(filePath);
45975
+ const rotatedPath = path5.join(dirname11, `${basename6}-${timestamp}${ext}`);
45976
45976
  fs5.renameSync(filePath, rotatedPath);
45977
45977
  }
45978
45978
  writeLog(level, message, meta) {
@@ -47918,11 +47918,11 @@ var init_systemPrompt = __esm({
47918
47918
 
47919
47919
  ### Rigorous Coding Habits
47920
47920
  - **Location Code**: Must First use a search tool to locate the line number of the code, then use \`filesystem-read\` to read the code content
47921
- - **Boundary verification**: MUST use \`filesystem-read\` to identify complete code boundaries before ANY edit. Never guess line numbers or code structure
47921
+ - **Boundary verification - COMPLETE CODE BLOCKS ONLY**: MUST use \`filesystem-read\` to identify COMPLETE code boundaries before ANY edit. Never guess line numbers or code structure. MANDATORY: verify ALL closing pairs are included - every \`{\` must have \`}\`, every \`(\` must have \`)\`, every \`[\` must have \`]\`, every \`<tag>\` must have \`</tag>\`. Count and match ALL opening/closing symbols before editing. ABSOLUTE PROHIBITIONS: NEVER edit partial functions (missing closing brace), NEVER edit incomplete HTML/XML/JSX tags (missing closing tag), NEVER edit partial code blocks (unmatched brackets/braces/parentheses).
47922
47922
  - **Impact analysis**: Consider modification impact and conflicts with existing business logic
47923
47923
  - **Optimal solution**: Avoid hardcoding/shortcuts unless explicitly requested
47924
47924
  - **Avoid duplication**: Search for existing reusable functions before creating new ones
47925
- - **Compilable code**: No syntax errors - always verify complete syntactic units
47925
+ - **Compilable code**: No syntax errors - always verify complete syntactic units with ALL opening/closing pairs matched
47926
47926
 
47927
47927
  ### Smart Action Mode
47928
47928
  **Principle: Understand enough to code correctly, but don't over-investigate**
@@ -47987,9 +47987,11 @@ AI: todo-add(content=["Read utils module structure", "Identify refactor targets"
47987
47987
  **CRITICAL: BOUNDARY-FIRST EDITING**
47988
47988
 
47989
47989
  **MANDATORY WORKFLOW:**
47990
- 1. **READ & VERIFY** - Use \`filesystem-read\` to identify COMPLETE units (functions: opening to closing brace, markup: full tags, check indentation)
47991
- 2. **COPY COMPLETE CODE** - Remove line numbers, preserve all content
47992
- 3. **EDIT** - \`filesystem-edit_search\` (fuzzy match, safer) or \`filesystem-edit\` (line-based, for add/delete)
47990
+ 1. **READ & VERIFY** - Use \`filesystem-read\` to identify COMPLETE units (functions: entire declaration to final closing brace \`}\`, HTML/XML/JSX markup: full opening \`<tag>\` to closing \`</tag>\` pairs, code blocks: ALL matching brackets/braces/parentheses with proper indentation)
47991
+ 2. **COUNT & MATCH** - Before editing, MANDATORY verification: count ALL opening and closing symbols - every \`{\` must have \`}\`, every \`(\` must have \`)\`, every \`[\` must have \`]\`, every \`<tag>\` must have \`</tag>\`. Verify indentation levels are consistent.
47992
+ 3. **COPY COMPLETE CODE** - Remove line numbers, preserve ALL content including ALL closing symbols
47993
+ 4. **ABSOLUTE PROHIBITIONS** - NEVER edit partial functions (missing closing brace \`}\`), NEVER edit incomplete markup (missing \`</tag>\`), NEVER edit partial code blocks (unmatched \`{\`, \`}\`, \`(\`, \`)\`, \`[\`, \`]\`), NEVER copy line numbers from filesystem-read output
47994
+ 5. **EDIT** - \`filesystem-edit_search\` (fuzzy match, safer) or \`filesystem-edit\` (line-based, for add/delete) - use ONLY after verification passes
47993
47995
 
47994
47996
  **BATCH OPERATIONS:** Modify 2+ files? Use batch: \`filesystem-read(filePath=["a.ts","b.ts"])\` or \`filesystem-edit_search(filePath=[{path:"a.ts",...},{path:"b.ts",...}])\`
47995
47997
 
@@ -60384,7 +60386,7 @@ var require_snapshot_recorder = __commonJS({
60384
60386
  "node_modules/undici/lib/mock/snapshot-recorder.js"(exports2, module2) {
60385
60387
  "use strict";
60386
60388
  var { writeFile: writeFile4, readFile: readFile3, mkdir: mkdir5 } = __require("node:fs/promises");
60387
- var { dirname: dirname10, resolve: resolve12 } = __require("node:path");
60389
+ var { dirname: dirname11, resolve: resolve12 } = __require("node:path");
60388
60390
  var { setTimeout: setTimeout2, clearTimeout: clearTimeout2 } = __require("node:timers");
60389
60391
  var { InvalidArgumentError, UndiciError } = require_errors();
60390
60392
  var { hashId, isUrlExcludedFactory, normalizeHeaders, createHeaderFilters } = require_snapshot_utils();
@@ -60608,7 +60610,7 @@ var require_snapshot_recorder = __commonJS({
60608
60610
  throw new InvalidArgumentError("Snapshot path is required");
60609
60611
  }
60610
60612
  const resolvedPath = resolve12(path53);
60611
- await mkdir5(dirname10(resolvedPath), { recursive: true });
60613
+ await mkdir5(dirname11(resolvedPath), { recursive: true });
60612
60614
  const data = Array.from(this.#snapshots.entries()).map(([hash, snapshot]) => ({
60613
60615
  hash,
60614
60616
  snapshot
@@ -76195,46 +76197,313 @@ var init_role = __esm({
76195
76197
  var skills_exports = {};
76196
76198
  __export(skills_exports, {
76197
76199
  checkSkillExists: () => checkSkillExists,
76200
+ createSkillFromGenerated: () => createSkillFromGenerated,
76198
76201
  createSkillTemplate: () => createSkillTemplate,
76199
76202
  default: () => skills_default,
76200
76203
  generateExamplesTemplate: () => generateExamplesTemplate,
76201
76204
  generateReferenceTemplate: () => generateReferenceTemplate,
76205
+ generateSkillDraftWithAI: () => generateSkillDraftWithAI,
76202
76206
  generateSkillTemplate: () => generateSkillTemplate,
76203
76207
  getSkillDirectory: () => getSkillDirectory,
76208
+ validateSkillId: () => validateSkillId,
76204
76209
  validateSkillName: () => validateSkillName
76205
76210
  });
76206
76211
  import { homedir as homedir8 } from "os";
76207
76212
  import { join as join10 } from "path";
76208
76213
  import { mkdir as mkdir2, writeFile as writeFile2 } from "fs/promises";
76209
76214
  import { existsSync as existsSync10 } from "fs";
76210
- function validateSkillName(name) {
76215
+ function validateSkillId(name) {
76211
76216
  if (!name || name.trim().length === 0) {
76212
76217
  return { valid: false, error: "Skill name cannot be empty" };
76213
76218
  }
76214
76219
  const trimmedName = name.trim();
76215
- if (trimmedName.length > 64) {
76216
- return { valid: false, error: "Skill name must be 64 characters or less" };
76220
+ if (trimmedName.length > 256) {
76221
+ return { valid: false, error: "Skill name must be 256 characters or less" };
76222
+ }
76223
+ if (trimmedName.includes("\\")) {
76224
+ return {
76225
+ valid: false,
76226
+ error: 'Skill name must use "/" as namespace separator (backslashes are not allowed)'
76227
+ };
76217
76228
  }
76218
- const validNamePattern = /^[a-z0-9-]+$/;
76219
- if (!validNamePattern.test(trimmedName)) {
76229
+ if (trimmedName.includes(":")) {
76230
+ return { valid: false, error: 'Skill name must not contain ":"' };
76231
+ }
76232
+ if (trimmedName.startsWith("/") || trimmedName.endsWith("/")) {
76233
+ return { valid: false, error: 'Skill name must not start or end with "/"' };
76234
+ }
76235
+ const segments = trimmedName.split("/");
76236
+ if (segments.some((segment) => segment.length === 0)) {
76220
76237
  return {
76221
76238
  valid: false,
76222
- error: "Skill name must contain only lowercase letters, numbers, and hyphens"
76239
+ error: "Skill name must not contain empty namespace segments"
76223
76240
  };
76224
76241
  }
76242
+ const validSegmentPattern = /^[a-z0-9-]+$/;
76243
+ for (const segment of segments) {
76244
+ if (segment === "." || segment === "..") {
76245
+ return {
76246
+ valid: false,
76247
+ error: 'Skill name must not contain "." or ".." segments'
76248
+ };
76249
+ }
76250
+ if (segment.length > 64) {
76251
+ return {
76252
+ valid: false,
76253
+ error: "Each skill name segment must be 64 characters or less"
76254
+ };
76255
+ }
76256
+ if (!validSegmentPattern.test(segment)) {
76257
+ return {
76258
+ valid: false,
76259
+ error: "Skill name segments must contain only lowercase letters, numbers, and hyphens"
76260
+ };
76261
+ }
76262
+ }
76225
76263
  return { valid: true };
76226
76264
  }
76265
+ function validateSkillName(name) {
76266
+ return validateSkillId(name);
76267
+ }
76268
+ function stripLeadingFrontMatter(markdown) {
76269
+ const content = markdown.trim();
76270
+ const descriptionPattern = /^---\s*[\s\S]*?---\s*/;
76271
+ if (descriptionPattern.test(content)) {
76272
+ return content.replace(descriptionPattern, "").trim();
76273
+ }
76274
+ return content;
76275
+ }
76276
+ function sanitizeSkillName(input2) {
76277
+ const raw = input2.trim().toLowerCase();
76278
+ const replaced = raw.replace(/[\s_]+/g, "-");
76279
+ const filtered = replaced.replace(/[^a-z0-9-]/g, "");
76280
+ const collapsed = filtered.replace(/-+/g, "-").replace(/^-|-$/g, "");
76281
+ return collapsed.slice(0, 64);
76282
+ }
76283
+ function makeUniqueSkillName(baseName, projectRoot) {
76284
+ const validation = validateSkillName(baseName);
76285
+ let safeBase = validation.valid ? baseName : sanitizeSkillName(baseName);
76286
+ if (!safeBase) {
76287
+ safeBase = "generated-skill";
76288
+ }
76289
+ let candidate = safeBase;
76290
+ let suffix = 2;
76291
+ while (checkSkillExists(candidate, "global") || checkSkillExists(candidate, "project", projectRoot)) {
76292
+ const suffixText = `-${suffix++}`;
76293
+ const maxBaseLen = 64 - suffixText.length;
76294
+ const truncatedBase = safeBase.slice(0, Math.max(1, maxBaseLen));
76295
+ candidate = `${truncatedBase}${suffixText}`;
76296
+ }
76297
+ return candidate;
76298
+ }
76299
+ function extractTaggedJson(text3) {
76300
+ const match2 = text3.match(/<json>\s*([\s\S]*?)\s*<\/json>/i);
76301
+ if (match2 && match2[1]) {
76302
+ return match2[1].trim();
76303
+ }
76304
+ return null;
76305
+ }
76306
+ function extractTaggedFiles(text3) {
76307
+ var _a21;
76308
+ const map3 = /* @__PURE__ */ new Map();
76309
+ const re = /<file\s+path="([^"]+)">\s*([\s\S]*?)\s*<\/file>/gi;
76310
+ let match2;
76311
+ while (match2 = re.exec(text3)) {
76312
+ const path53 = (_a21 = match2[1]) == null ? void 0 : _a21.trim();
76313
+ const content = match2[2] ?? "";
76314
+ if (path53) {
76315
+ map3.set(path53, content);
76316
+ }
76317
+ }
76318
+ return map3;
76319
+ }
76320
+ function buildSkillGenerationSystemPrompt() {
76321
+ return `You create Snow CLI Skills (Claude Code compatible).
76322
+
76323
+ Rules (MUST FOLLOW):
76324
+ 1) Output MUST ONLY contain: <json>...</json> and <file path="...">...</file> blocks. No other text.
76325
+ 2) The <json> block MUST be valid JSON with keys: name, description.
76326
+ 3) name MUST be a directory-safe slug: lowercase letters, numbers, hyphens only (^[a-z0-9-]+$), max 64 chars.
76327
+ 4) description and ALL file contents MUST be written in the SAME LANGUAGE as the user's requirement.
76328
+ 5) Generate exactly 3 file blocks with these paths (case-sensitive):
76329
+ - SKILL.md
76330
+ - reference.md
76331
+ - examples.md
76332
+ 6) The SKILL.md content MUST NOT include YAML front matter. Start with a single H1 title and include these sections:
76333
+ - ## Instructions
76334
+ - ### Context
76335
+ - ### Steps (numbered)
76336
+ - ## Examples (at least 2)
76337
+ - ## Best Practices
76338
+ - ## Common Pitfalls
76339
+ - ## Related Skills
76340
+ - ## References
76341
+ 7) Do NOT mention or include allowed-tools (Snow CLI will manage it).
76342
+
76343
+ Quality bar:
76344
+ - Be concrete, step-by-step, with realistic examples.
76345
+ - Keep it helpful and production-oriented.`;
76346
+ }
76347
+ function buildSkillGenerationUserPrompt(requirement) {
76348
+ return `Generate a Snow CLI Skill from the requirement below.
76349
+
76350
+ CRITICAL OUTPUT FORMAT (no extra text):
76351
+ <json>
76352
+ {"name":"example-skill","description":"..."}
76353
+ </json>
76354
+ <file path="SKILL.md">
76355
+ # ...
76356
+ </file>
76357
+ <file path="reference.md">
76358
+ # ...
76359
+ </file>
76360
+ <file path="examples.md">
76361
+ # ...
76362
+ </file>
76363
+
76364
+ Rules:
76365
+ - Output ONLY the <json> and <file> blocks.
76366
+ - <json> must be valid JSON with keys: name, description (no other keys).
76367
+ - name must be a slug: lowercase letters, numbers, hyphens only (^[a-z0-9-]+$), max 64 chars.
76368
+ - description and ALL file contents MUST be written in the SAME LANGUAGE as the requirement.
76369
+ - The SKILL.md content MUST NOT include YAML front matter.
76370
+ - Do NOT mention allowed-tools.
76371
+
76372
+ Requirement:
76373
+ ${requirement}`;
76374
+ }
76375
+ async function callModelForText(messages, abortSignal) {
76376
+ var _a21, _b14;
76377
+ const config3 = getOpenAiConfig();
76378
+ const model = config3.advancedModel || config3.basicModel;
76379
+ if (!model) {
76380
+ throw new Error("\u672A\u914D\u7F6E\u6A21\u578B\uFF0C\u8BF7\u5148\u5728\u8BBE\u7F6E\u4E2D\u9009\u62E9\u6A21\u578B");
76381
+ }
76382
+ let stream;
76383
+ switch (config3.requestMethod) {
76384
+ case "anthropic":
76385
+ stream = createStreamingAnthropicCompletion({
76386
+ model,
76387
+ messages,
76388
+ max_tokens: 3e3,
76389
+ includeBuiltinSystemPrompt: false,
76390
+ disableThinking: true
76391
+ }, abortSignal);
76392
+ break;
76393
+ case "gemini":
76394
+ stream = createStreamingGeminiCompletion({
76395
+ model,
76396
+ messages,
76397
+ includeBuiltinSystemPrompt: false
76398
+ }, abortSignal);
76399
+ break;
76400
+ case "responses":
76401
+ stream = createStreamingResponse({
76402
+ model,
76403
+ messages,
76404
+ includeBuiltinSystemPrompt: false,
76405
+ tool_choice: "none"
76406
+ }, abortSignal);
76407
+ break;
76408
+ case "chat":
76409
+ default:
76410
+ stream = createStreamingChatCompletion({
76411
+ model,
76412
+ messages,
76413
+ includeBuiltinSystemPrompt: false,
76414
+ // NOTE: chat.ts uses `options.temperature || 0.7`, so 0 would be ignored.
76415
+ temperature: 1e-4
76416
+ }, abortSignal);
76417
+ break;
76418
+ }
76419
+ let text3 = "";
76420
+ for await (const chunk2 of stream) {
76421
+ if (abortSignal == null ? void 0 : abortSignal.aborted) {
76422
+ throw new Error("Request aborted");
76423
+ }
76424
+ if (chunk2 && typeof chunk2 === "object") {
76425
+ if (chunk2.type === "content" && typeof chunk2.content === "string") {
76426
+ text3 += chunk2.content;
76427
+ continue;
76428
+ }
76429
+ const maybeChoices = chunk2.choices;
76430
+ const deltaContent = (_b14 = (_a21 = maybeChoices == null ? void 0 : maybeChoices[0]) == null ? void 0 : _a21.delta) == null ? void 0 : _b14.content;
76431
+ if (typeof deltaContent === "string") {
76432
+ text3 += deltaContent;
76433
+ }
76434
+ }
76435
+ }
76436
+ if (!text3.trim()) {
76437
+ throw new Error("\u6A21\u578B\u672A\u8FD4\u56DE\u53EF\u7528\u5185\u5BB9");
76438
+ }
76439
+ return text3;
76440
+ }
76441
+ async function generateSkillDraftWithAI(requirement, projectRoot, abortSignal) {
76442
+ const trimmed = requirement.trim();
76443
+ if (!trimmed) {
76444
+ throw new Error("\u6280\u80FD\u9700\u6C42\u4E0D\u80FD\u4E3A\u7A7A");
76445
+ }
76446
+ const systemPrompt = buildSkillGenerationSystemPrompt();
76447
+ const userPrompt = buildSkillGenerationUserPrompt(trimmed);
76448
+ const messages = [
76449
+ { role: "system", content: systemPrompt },
76450
+ { role: "user", content: userPrompt }
76451
+ ];
76452
+ const raw = await callModelForText(messages, abortSignal);
76453
+ const jsonText = extractTaggedJson(raw);
76454
+ const files = extractTaggedFiles(raw);
76455
+ if (!jsonText) {
76456
+ throw new Error("AI \u8F93\u51FA\u7F3A\u5C11 <json> \u5757");
76457
+ }
76458
+ const parseResult = parseJsonWithFix(jsonText, {
76459
+ toolName: "skills ai json",
76460
+ logWarning: true,
76461
+ logError: true
76462
+ });
76463
+ if (!parseResult.success || !parseResult.data) {
76464
+ throw new Error("AI \u8F93\u51FA JSON \u89E3\u6790\u5931\u8D25");
76465
+ }
76466
+ const nameRaw = typeof parseResult.data.name === "string" ? parseResult.data.name.trim() : "";
76467
+ const descriptionRaw = typeof parseResult.data.description === "string" ? parseResult.data.description.trim() : "";
76468
+ const skillBody = files.get("SKILL.md");
76469
+ const referenceMd = files.get("reference.md");
76470
+ const examplesMd = files.get("examples.md");
76471
+ if (!skillBody || !referenceMd || !examplesMd) {
76472
+ throw new Error("AI \u8F93\u51FA\u7F3A\u5C11\u6587\u4EF6\u5185\u5BB9\uFF08\u9700\u8981 SKILL.md/reference.md/examples.md\uFF09");
76473
+ }
76474
+ const uniqueName = makeUniqueSkillName(nameRaw, projectRoot);
76475
+ return {
76476
+ skillName: uniqueName,
76477
+ description: descriptionRaw || uniqueName,
76478
+ generated: {
76479
+ skillMarkdownBody: stripLeadingFrontMatter(skillBody),
76480
+ referenceMarkdown: stripLeadingFrontMatter(referenceMd),
76481
+ examplesMarkdown: stripLeadingFrontMatter(examplesMd)
76482
+ }
76483
+ };
76484
+ }
76485
+ function generateSkillMarkdownWithFrontMatter(metadata, bodyMarkdown) {
76486
+ const cleanedBody = stripLeadingFrontMatter(bodyMarkdown).trim();
76487
+ return `---
76488
+ name: ${metadata.name}
76489
+ description: ${metadata.description}
76490
+ allowed-tools:
76491
+ ---
76492
+
76493
+ ${cleanedBody}
76494
+ `;
76495
+ }
76227
76496
  function checkSkillExists(skillName, location, projectRoot) {
76228
76497
  const skillDir = getSkillDirectory(skillName, location, projectRoot);
76229
76498
  return existsSync10(skillDir);
76230
76499
  }
76231
76500
  function getSkillDirectory(skillName, location, projectRoot) {
76501
+ const segments = skillName.split("/").filter(Boolean);
76232
76502
  if (location === "global") {
76233
- return join10(homedir8(), ".snow", "skills", skillName);
76234
- } else {
76235
- const root2 = projectRoot || process.cwd();
76236
- return join10(root2, ".snow", "skills", skillName);
76503
+ return join10(homedir8(), ".snow", "skills", ...segments);
76237
76504
  }
76505
+ const root2 = projectRoot || process.cwd();
76506
+ return join10(root2, ".snow", "skills", ...segments);
76238
76507
  }
76239
76508
  function generateSkillTemplate(metadata) {
76240
76509
  return `---
@@ -76360,6 +76629,69 @@ What this advanced example demonstrates.
76360
76629
  **Result:** What was achieved
76361
76630
  `;
76362
76631
  }
76632
+ async function createSkillFromGenerated(skillName, description, generated, location, projectRoot) {
76633
+ try {
76634
+ const skillDir = getSkillDirectory(skillName, location, projectRoot);
76635
+ if (existsSync10(skillDir)) {
76636
+ return {
76637
+ success: false,
76638
+ path: skillDir,
76639
+ error: `Skill "${skillName}" already exists at ${skillDir}`
76640
+ };
76641
+ }
76642
+ await mkdir2(skillDir, { recursive: true });
76643
+ await mkdir2(join10(skillDir, "scripts"), { recursive: true });
76644
+ await mkdir2(join10(skillDir, "templates"), { recursive: true });
76645
+ const leafName = skillName.split("/").filter(Boolean).pop() || skillName;
76646
+ const skillContent = generateSkillMarkdownWithFrontMatter({ name: leafName, description }, generated.skillMarkdownBody);
76647
+ await writeFile2(join10(skillDir, "SKILL.md"), skillContent, "utf-8");
76648
+ await writeFile2(join10(skillDir, "reference.md"), generated.referenceMarkdown.trim() + "\n", "utf-8");
76649
+ await writeFile2(join10(skillDir, "examples.md"), generated.examplesMarkdown.trim() + "\n", "utf-8");
76650
+ const templateContent = `This is a template file for ${skillName}.
76651
+
76652
+ You can use this as a starting point for generating code, configurations, or documentation.
76653
+
76654
+ Variables can be referenced like: {{variable_name}}
76655
+ `;
76656
+ await writeFile2(join10(skillDir, "templates", "template.txt"), templateContent, "utf-8");
76657
+ const scriptContent = `#!/usr/bin/env python3
76658
+ """
76659
+ Helper script for ${skillName}
76660
+
76661
+ Usage:
76662
+ python scripts/helper.py <input_file>
76663
+ """
76664
+
76665
+ import sys
76666
+
76667
+ def main():
76668
+ if len(sys.argv) < 2:
76669
+ print("Usage: python helper.py <input_file>")
76670
+ sys.exit(1)
76671
+
76672
+ input_file = sys.argv[1]
76673
+ print(f"Processing {input_file}...")
76674
+
76675
+ # Add your processing logic here
76676
+
76677
+ print("Done!")
76678
+
76679
+ if __name__ == "__main__":
76680
+ main()
76681
+ `;
76682
+ await writeFile2(join10(skillDir, "scripts", "helper.py"), scriptContent, "utf-8");
76683
+ return {
76684
+ success: true,
76685
+ path: skillDir
76686
+ };
76687
+ } catch (error) {
76688
+ return {
76689
+ success: false,
76690
+ path: "",
76691
+ error: error instanceof Error ? error.message : "Unknown error"
76692
+ };
76693
+ }
76694
+ }
76363
76695
  async function createSkillTemplate(skillName, description, location, projectRoot) {
76364
76696
  try {
76365
76697
  const skillDir = getSkillDirectory(skillName, location, projectRoot);
@@ -76373,7 +76705,8 @@ async function createSkillTemplate(skillName, description, location, projectRoot
76373
76705
  await mkdir2(skillDir, { recursive: true });
76374
76706
  await mkdir2(join10(skillDir, "scripts"), { recursive: true });
76375
76707
  await mkdir2(join10(skillDir, "templates"), { recursive: true });
76376
- const skillContent = generateSkillTemplate({ name: skillName, description });
76708
+ const leafName = skillName.split("/").filter(Boolean).pop() || skillName;
76709
+ const skillContent = generateSkillTemplate({ name: leafName, description });
76377
76710
  await writeFile2(join10(skillDir, "SKILL.md"), skillContent, "utf-8");
76378
76711
  const referenceContent = generateReferenceTemplate();
76379
76712
  await writeFile2(join10(skillDir, "reference.md"), referenceContent, "utf-8");
@@ -76429,6 +76762,12 @@ var init_skills = __esm({
76429
76762
  "dist/utils/commands/skills.js"() {
76430
76763
  "use strict";
76431
76764
  init_commandExecutor();
76765
+ init_apiConfig();
76766
+ init_chat();
76767
+ init_responses();
76768
+ init_gemini();
76769
+ init_anthropic();
76770
+ init_retryUtils();
76432
76771
  registerCommand("skills", {
76433
76772
  execute: async () => {
76434
76773
  return {
@@ -80592,7 +80931,12 @@ var init_en = __esm({
80592
80931
  confirmSave: "Save this custom command? (y/n)",
80593
80932
  confirmYes: "Yes",
80594
80933
  confirmNo: "Cancel",
80595
- escCancel: "Press ESC to cancel"
80934
+ escCancel: "Press ESC to cancel",
80935
+ resultTypeExecute: "Execute in terminal",
80936
+ resultTypePrompt: "Send to AI",
80937
+ resultLocationGlobal: "Global (~/.snow/commands/)",
80938
+ resultLocationProject: "Project (.snow/commands/)",
80939
+ saveSuccessMessage: "Custom command '{name}' saved successfully!\nType: {type}\nLocation: {location}\nYou can now use /{name}"
80596
80940
  },
80597
80941
  chatScreen: {
80598
80942
  // Header
@@ -80798,9 +81142,24 @@ var init_en = __esm({
80798
81142
  },
80799
81143
  skillsCreation: {
80800
81144
  title: "Create New Skill",
81145
+ modeLabel: "Creation Mode:",
81146
+ modeAi: "AI Generate (describe requirement)",
81147
+ modeManual: "Manual (create templates)",
81148
+ requirementLabel: "Requirement:",
81149
+ requirementHint: "Describe what you want this Skill to do (content will follow this language)",
81150
+ requirementPlaceholder: "e.g., Generate a Skill for releasing npm packages...",
81151
+ generatingLabel: "AI Generating...",
81152
+ generatingMessage: "Generating skill files, please wait",
81153
+ filesLabel: "Files to be created:",
81154
+ editName: "Edit Name",
81155
+ editNameLabel: "Current Skill Name:",
81156
+ editNameHint: "Enter a new skill name (lowercase letters/numbers/hyphens, max 64 chars)",
81157
+ editNamePlaceholder: "new-skill-name",
81158
+ regenerate: "Regenerate",
81159
+ cancel: "Cancel",
80801
81160
  nameLabel: "Skill Name:",
80802
- nameHint: "Use lowercase letters, numbers, and hyphens only (max 64 chars)",
80803
- namePlaceholder: "my-skill-name",
81161
+ nameHint: 'Use lowercase letters, numbers, and hyphens. Use "/" to namespace (max 64 chars per segment)',
81162
+ namePlaceholder: "team/my-skill-name",
80804
81163
  descriptionLabel: "Description:",
80805
81164
  descriptionHint: "Brief description of what this Skill does and when to use it",
80806
81165
  descriptionPlaceholder: "A brief description...",
@@ -80817,7 +81176,15 @@ var init_en = __esm({
80817
81176
  errorInvalidName: "Invalid skill name",
80818
81177
  errorExistsBoth: 'Skill "{name}" already exists in both global and project locations',
80819
81178
  errorExistsGlobal: 'Skill "{name}" already exists in global location (~/.snow/skills/)',
80820
- errorExistsProject: 'Skill "{name}" already exists in project location (.snow/skills/)'
81179
+ errorExistsProject: 'Skill "{name}" already exists in project location (.snow/skills/)',
81180
+ errorExistsAny: 'Skill "{name}" already exists, please choose another name',
81181
+ errorGeneration: "AI generation failed",
81182
+ errorNoGeneratedContent: "No generated content, please retry",
81183
+ resultModeAi: "AI Generated",
81184
+ resultModeManual: "Manual Template",
81185
+ createSuccessMessage: 'Skill "{name}" created successfully!\nMode: {mode}\nLocation: {location}\nPath: {path}\n\nThe following files have been created:\n- SKILL.md (main skill documentation)\n- reference.md (detailed reference)\n- examples.md (usage examples)\n- templates/template.txt (template file)\n- scripts/helper.py (helper script)\n\nYou can now edit these files to customize your skill.',
81186
+ createErrorMessage: "Failed to create skill: {error}",
81187
+ errorUnknown: "Unknown error"
80821
81188
  },
80822
81189
  askUser: {
80823
81190
  header: "[User Input Required]",
@@ -81563,7 +81930,12 @@ var init_zh = __esm({
81563
81930
  confirmSave: "\u4FDD\u5B58\u6B64\u81EA\u5B9A\u4E49\u547D\u4EE4? (y/n)",
81564
81931
  confirmYes: "Yes",
81565
81932
  confirmNo: "Cancel",
81566
- escCancel: "\u6309 ESC \u53D6\u6D88"
81933
+ escCancel: "\u6309 ESC \u53D6\u6D88",
81934
+ resultTypeExecute: "\u5728\u7EC8\u7AEF\u6267\u884C",
81935
+ resultTypePrompt: "\u53D1\u9001\u7ED9 AI",
81936
+ resultLocationGlobal: "\u5168\u5C40 (~/.snow/commands/)",
81937
+ resultLocationProject: "\u9879\u76EE (.snow/commands/)",
81938
+ saveSuccessMessage: "\u81EA\u5B9A\u4E49\u547D\u4EE4 '{name}' \u4FDD\u5B58\u6210\u529F\uFF01\n\u7C7B\u578B: {type}\n\u4F4D\u7F6E: {location}\n\u4F60\u73B0\u5728\u53EF\u4EE5\u4F7F\u7528 /{name}"
81567
81939
  },
81568
81940
  chatScreen: {
81569
81941
  // Header
@@ -81769,9 +82141,24 @@ var init_zh = __esm({
81769
82141
  },
81770
82142
  skillsCreation: {
81771
82143
  title: "\u521B\u5EFA\u65B0\u6280\u80FD",
82144
+ modeLabel: "\u9009\u62E9\u521B\u5EFA\u65B9\u5F0F:",
82145
+ modeAi: "AI \u751F\u6210\uFF08\u8F93\u5165\u9700\u6C42\u5373\u53EF\uFF09",
82146
+ modeManual: "\u624B\u52A8\u521B\u5EFA\uFF08\u751F\u6210\u6A21\u677F\uFF09",
82147
+ requirementLabel: "\u6280\u80FD\u9700\u6C42:",
82148
+ requirementHint: "\u7B80\u8981\u63CF\u8FF0\u4F60\u5E0C\u671B\u8BE5\u6280\u80FD\u5B8C\u6210\u4EC0\u4E48\uFF08\u751F\u6210\u5185\u5BB9\u5C06\u8DDF\u968F\u6B64\u8BED\u8A00\uFF09",
82149
+ requirementPlaceholder: "\u4F8B\u5982\uFF1A\u751F\u6210\u4E00\u4E2A\u7528\u4E8E\u53D1\u5E03 npm \u5305\u7684\u6280\u80FD\u2026",
82150
+ generatingLabel: "AI \u751F\u6210\u4E2D...",
82151
+ generatingMessage: "\u6B63\u5728\u751F\u6210\u6280\u80FD\u6587\u4EF6\uFF0C\u8BF7\u7A0D\u7B49",
82152
+ filesLabel: "\u5C06\u521B\u5EFA\u6587\u4EF6:",
82153
+ editName: "\u7F16\u8F91\u540D\u79F0",
82154
+ editNameLabel: "\u5F53\u524D\u6280\u80FD\u540D\u79F0:",
82155
+ editNameHint: "\u8F93\u5165\u65B0\u7684\u6280\u80FD\u540D\u79F0\uFF08\u5C0F\u5199\u5B57\u6BCD/\u6570\u5B57/\u8FDE\u5B57\u7B26\uFF0C\u6700\u591A 64 \u4E2A\u5B57\u7B26\uFF09",
82156
+ editNamePlaceholder: "new-skill-name",
82157
+ regenerate: "\u91CD\u65B0\u751F\u6210",
82158
+ cancel: "\u53D6\u6D88",
81772
82159
  nameLabel: "\u6280\u80FD\u540D\u79F0:",
81773
- nameHint: "\u4EC5\u4F7F\u7528\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26\uFF08\u6700\u591A 64 \u4E2A\u5B57\u7B26\uFF09",
81774
- namePlaceholder: "my-skill-name",
82160
+ nameHint: '\u4EC5\u4F7F\u7528\u5C0F\u5199\u5B57\u6BCD\u3001\u6570\u5B57\u548C\u8FDE\u5B57\u7B26\uFF0C\u53EF\u7528 "/" \u4F5C\u4E3A\u547D\u540D\u7A7A\u95F4\u5206\u9694\uFF08\u6BCF\u6BB5\u6700\u591A 64 \u4E2A\u5B57\u7B26\uFF09',
82161
+ namePlaceholder: "team/my-skill-name",
81775
82162
  descriptionLabel: "\u63CF\u8FF0:",
81776
82163
  descriptionHint: "\u7B80\u8981\u63CF\u8FF0\u6B64\u6280\u80FD\u7684\u7528\u9014\u548C\u4F7F\u7528\u573A\u666F",
81777
82164
  descriptionPlaceholder: "\u7B80\u8981\u63CF\u8FF0...",
@@ -81788,7 +82175,15 @@ var init_zh = __esm({
81788
82175
  errorInvalidName: "\u65E0\u6548\u7684\u6280\u80FD\u540D\u79F0",
81789
82176
  errorExistsBoth: '\u6280\u80FD "{name}" \u5728\u5168\u5C40\u548C\u9879\u76EE\u4F4D\u7F6E\u90FD\u5DF2\u5B58\u5728',
81790
82177
  errorExistsGlobal: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u4E8E\u5168\u5C40\u4F4D\u7F6E (~/.snow/skills/)',
81791
- errorExistsProject: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u4E8E\u9879\u76EE\u4F4D\u7F6E (.snow/skills/)'
82178
+ errorExistsProject: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u4E8E\u9879\u76EE\u4F4D\u7F6E (.snow/skills/)',
82179
+ errorExistsAny: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\uFF0C\u8BF7\u6362\u4E00\u4E2A\u540D\u79F0',
82180
+ errorGeneration: "AI \u751F\u6210\u5931\u8D25",
82181
+ errorNoGeneratedContent: "\u7F3A\u5C11\u751F\u6210\u5185\u5BB9\uFF0C\u8BF7\u91CD\u8BD5",
82182
+ resultModeAi: "AI \u751F\u6210",
82183
+ resultModeManual: "\u624B\u52A8\u6A21\u677F",
82184
+ createSuccessMessage: '\u6280\u80FD "{name}" \u521B\u5EFA\u6210\u529F\uFF01\n\u6A21\u5F0F: {mode}\n\u4F4D\u7F6E: {location}\n\u8DEF\u5F84: {path}\n\n\u5DF2\u521B\u5EFA\u4EE5\u4E0B\u6587\u4EF6\uFF1A\n- SKILL.md\uFF08\u4E3B\u6280\u80FD\u6587\u6863\uFF09\n- reference.md\uFF08\u8BE6\u7EC6\u53C2\u8003\uFF09\n- examples.md\uFF08\u4F7F\u7528\u793A\u4F8B\uFF09\n- templates/template.txt\uFF08\u6A21\u677F\u6587\u4EF6\uFF09\n- scripts/helper.py\uFF08\u8F85\u52A9\u811A\u672C\uFF09\n\n\u4F60\u73B0\u5728\u53EF\u4EE5\u7F16\u8F91\u8FD9\u4E9B\u6587\u4EF6\u6765\u81EA\u5B9A\u4E49\u6280\u80FD\u3002',
82185
+ createErrorMessage: "\u521B\u5EFA\u6280\u80FD\u5931\u8D25\uFF1A{error}",
82186
+ errorUnknown: "\u672A\u77E5\u9519\u8BEF"
81792
82187
  },
81793
82188
  askUser: {
81794
82189
  header: "[\u9700\u8981\u7528\u6237\u8F93\u5165]",
@@ -82534,7 +82929,12 @@ var init_zh_TW = __esm({
82534
82929
  confirmSave: "Save this custom command? (y/n)",
82535
82930
  confirmYes: "Yes",
82536
82931
  confirmNo: "Cancel",
82537
- escCancel: "Press ESC to cancel"
82932
+ escCancel: "Press ESC to cancel",
82933
+ resultTypeExecute: "\u5728\u7D42\u7AEF\u57F7\u884C",
82934
+ resultTypePrompt: "\u50B3\u9001\u7D66 AI",
82935
+ resultLocationGlobal: "\u5168\u57DF (~/.snow/commands/)",
82936
+ resultLocationProject: "\u5C08\u6848 (.snow/commands/)",
82937
+ saveSuccessMessage: "\u81EA\u8A02\u547D\u4EE4 '{name}' \u5132\u5B58\u6210\u529F\uFF01\n\u985E\u578B: {type}\n\u4F4D\u7F6E: {location}\n\u4F60\u73FE\u5728\u53EF\u4EE5\u4F7F\u7528 /{name}"
82538
82938
  },
82539
82939
  chatScreen: {
82540
82940
  // Header
@@ -82740,6 +83140,21 @@ var init_zh_TW = __esm({
82740
83140
  },
82741
83141
  skillsCreation: {
82742
83142
  title: "\u5275\u5EFA\u65B0\u6280\u80FD",
83143
+ modeLabel: "\u9078\u64C7\u5275\u5EFA\u65B9\u5F0F:",
83144
+ modeAi: "AI \u751F\u6210\uFF08\u8F38\u5165\u9700\u6C42\u5373\u53EF\uFF09",
83145
+ modeManual: "\u624B\u52D5\u5275\u5EFA\uFF08\u751F\u6210\u6A21\u677F\uFF09",
83146
+ requirementLabel: "\u6280\u80FD\u9700\u6C42:",
83147
+ requirementHint: "\u7C21\u8981\u63CF\u8FF0\u4F60\u5E0C\u671B\u8A72\u6280\u80FD\u5B8C\u6210\u4EC0\u9EBC\uFF08\u751F\u6210\u5167\u5BB9\u5C07\u8DDF\u96A8\u6B64\u8A9E\u8A00\uFF09",
83148
+ requirementPlaceholder: "\u4F8B\u5982\uFF1A\u751F\u6210\u4E00\u500B\u7528\u65BC\u767C\u4F48 npm \u5957\u4EF6\u7684\u6280\u80FD\u2026",
83149
+ generatingLabel: "AI \u751F\u6210\u4E2D...",
83150
+ generatingMessage: "\u6B63\u5728\u751F\u6210\u6280\u80FD\u6A94\u6848\uFF0C\u8ACB\u7A0D\u7B49",
83151
+ filesLabel: "\u5C07\u5275\u5EFA\u6A94\u6848:",
83152
+ editName: "\u7DE8\u8F2F\u540D\u7A31",
83153
+ editNameLabel: "\u76EE\u524D\u6280\u80FD\u540D\u7A31:",
83154
+ editNameHint: "\u8F38\u5165\u65B0\u7684\u6280\u80FD\u540D\u7A31\uFF08\u5C0F\u5BEB\u5B57\u6BCD/\u6578\u5B57/\u9023\u5B57\u7B26\uFF0C\u6700\u591A 64 \u500B\u5B57\u7B26\uFF09",
83155
+ editNamePlaceholder: "new-skill-name",
83156
+ regenerate: "\u91CD\u65B0\u751F\u6210",
83157
+ cancel: "\u53D6\u6D88",
82743
83158
  nameLabel: "\u6280\u80FD\u540D\u7A31:",
82744
83159
  nameHint: "\u50C5\u4F7F\u7528\u5C0F\u5BEB\u5B57\u6BCD\u3001\u6578\u5B57\u548C\u9023\u5B57\u7B26\uFF08\u6700\u591A 64 \u500B\u5B57\u7B26\uFF09",
82745
83160
  namePlaceholder: "my-skill-name",
@@ -82758,7 +83173,15 @@ var init_zh_TW = __esm({
82758
83173
  errorInvalidName: "\u7121\u6548\u7684\u6280\u80FD\u540D\u7A31",
82759
83174
  errorExistsBoth: '\u6280\u80FD "{name}" \u5728\u5168\u5C40\u548C\u9805\u76EE\u4F4D\u7F6E\u90FD\u5DF2\u5B58\u5728',
82760
83175
  errorExistsGlobal: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u65BC\u5168\u5C40\u4F4D\u7F6E (~/.snow/skills/)',
82761
- errorExistsProject: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u65BC\u9805\u76EE\u4F4D\u7F6E (.snow/skills/)'
83176
+ errorExistsProject: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\u65BC\u9805\u76EE\u4F4D\u7F6E (.snow/skills/)',
83177
+ errorExistsAny: '\u6280\u80FD "{name}" \u5DF2\u5B58\u5728\uFF0C\u8ACB\u63DB\u4E00\u500B\u540D\u7A31',
83178
+ errorGeneration: "AI \u751F\u6210\u5931\u6557",
83179
+ errorNoGeneratedContent: "\u7F3A\u5C11\u751F\u6210\u5167\u5BB9\uFF0C\u8ACB\u91CD\u8A66",
83180
+ resultModeAi: "AI \u751F\u6210",
83181
+ resultModeManual: "\u624B\u52D5\u6A21\u677F",
83182
+ createSuccessMessage: '\u6280\u80FD "{name}" \u5275\u5EFA\u6210\u529F\uFF01\n\u6A21\u5F0F: {mode}\n\u4F4D\u7F6E: {location}\n\u8DEF\u5F91: {path}\n\n\u5DF2\u5275\u5EFA\u4EE5\u4E0B\u6A94\u6848\uFF1A\n- SKILL.md\uFF08\u4E3B\u6280\u80FD\u6587\u4EF6\uFF09\n- reference.md\uFF08\u8A73\u7D30\u53C3\u8003\uFF09\n- examples.md\uFF08\u4F7F\u7528\u7BC4\u4F8B\uFF09\n- templates/template.txt\uFF08\u6A21\u677F\u6A94\u6848\uFF09\n- scripts/helper.py\uFF08\u8F14\u52A9\u8173\u672C\uFF09\n\n\u4F60\u73FE\u5728\u53EF\u4EE5\u7DE8\u8F2F\u9019\u4E9B\u6A94\u6848\u4F86\u81EA\u8A02\u6280\u80FD\u3002',
83183
+ createErrorMessage: "\u5275\u5EFA\u6280\u80FD\u5931\u6557\uFF1A{error}",
83184
+ errorUnknown: "\u672A\u77E5\u932F\u8AA4"
82762
83185
  },
82763
83186
  askUser: {
82764
83187
  header: "[\u9700\u8981\u4F7F\u7528\u8005\u8F38\u5165]",
@@ -98766,49 +99189,49 @@ var require_fast_uri = __commonJS({
98766
99189
  schemelessOptions.skipEscape = true;
98767
99190
  return serialize(resolved, schemelessOptions);
98768
99191
  }
98769
- function resolveComponent(base, relative8, options3, skipNormalization) {
99192
+ function resolveComponent(base, relative9, options3, skipNormalization) {
98770
99193
  const target = {};
98771
99194
  if (!skipNormalization) {
98772
99195
  base = parse3(serialize(base, options3), options3);
98773
- relative8 = parse3(serialize(relative8, options3), options3);
99196
+ relative9 = parse3(serialize(relative9, options3), options3);
98774
99197
  }
98775
99198
  options3 = options3 || {};
98776
- if (!options3.tolerant && relative8.scheme) {
98777
- target.scheme = relative8.scheme;
98778
- target.userinfo = relative8.userinfo;
98779
- target.host = relative8.host;
98780
- target.port = relative8.port;
98781
- target.path = removeDotSegments(relative8.path || "");
98782
- target.query = relative8.query;
99199
+ if (!options3.tolerant && relative9.scheme) {
99200
+ target.scheme = relative9.scheme;
99201
+ target.userinfo = relative9.userinfo;
99202
+ target.host = relative9.host;
99203
+ target.port = relative9.port;
99204
+ target.path = removeDotSegments(relative9.path || "");
99205
+ target.query = relative9.query;
98783
99206
  } else {
98784
- if (relative8.userinfo !== void 0 || relative8.host !== void 0 || relative8.port !== void 0) {
98785
- target.userinfo = relative8.userinfo;
98786
- target.host = relative8.host;
98787
- target.port = relative8.port;
98788
- target.path = removeDotSegments(relative8.path || "");
98789
- target.query = relative8.query;
99207
+ if (relative9.userinfo !== void 0 || relative9.host !== void 0 || relative9.port !== void 0) {
99208
+ target.userinfo = relative9.userinfo;
99209
+ target.host = relative9.host;
99210
+ target.port = relative9.port;
99211
+ target.path = removeDotSegments(relative9.path || "");
99212
+ target.query = relative9.query;
98790
99213
  } else {
98791
- if (!relative8.path) {
99214
+ if (!relative9.path) {
98792
99215
  target.path = base.path;
98793
- if (relative8.query !== void 0) {
98794
- target.query = relative8.query;
99216
+ if (relative9.query !== void 0) {
99217
+ target.query = relative9.query;
98795
99218
  } else {
98796
99219
  target.query = base.query;
98797
99220
  }
98798
99221
  } else {
98799
- if (relative8.path[0] === "/") {
98800
- target.path = removeDotSegments(relative8.path);
99222
+ if (relative9.path[0] === "/") {
99223
+ target.path = removeDotSegments(relative9.path);
98801
99224
  } else {
98802
99225
  if ((base.userinfo !== void 0 || base.host !== void 0 || base.port !== void 0) && !base.path) {
98803
- target.path = "/" + relative8.path;
99226
+ target.path = "/" + relative9.path;
98804
99227
  } else if (!base.path) {
98805
- target.path = relative8.path;
99228
+ target.path = relative9.path;
98806
99229
  } else {
98807
- target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative8.path;
99230
+ target.path = base.path.slice(0, base.path.lastIndexOf("/") + 1) + relative9.path;
98808
99231
  }
98809
99232
  target.path = removeDotSegments(target.path);
98810
99233
  }
98811
- target.query = relative8.query;
99234
+ target.query = relative9.query;
98812
99235
  }
98813
99236
  target.userinfo = base.userinfo;
98814
99237
  target.host = base.host;
@@ -98816,7 +99239,7 @@ var require_fast_uri = __commonJS({
98816
99239
  }
98817
99240
  target.scheme = base.scheme;
98818
99241
  }
98819
- target.fragment = relative8.fragment;
99242
+ target.fragment = relative9.fragment;
98820
99243
  return target;
98821
99244
  }
98822
99245
  function equal(uriA, uriB, options3) {
@@ -280486,7 +280909,7 @@ var require_files = __commonJS({
280486
280909
  var fs42 = __require("fs");
280487
280910
  var url = __require("url");
280488
280911
  var os23 = __require("os");
280489
- var dirname10 = __require("path").dirname;
280912
+ var dirname11 = __require("path").dirname;
280490
280913
  var resolvePath = __require("path").resolve;
280491
280914
  var isAbsolutePath = require_path_is_absolute();
280492
280915
  var promises = require_promises();
@@ -280501,7 +280924,7 @@ var require_files = __commonJS({
280501
280924
  }
280502
280925
  };
280503
280926
  }
280504
- var base = options3.relativeToFile ? dirname10(options3.relativeToFile) : null;
280927
+ var base = options3.relativeToFile ? dirname11(options3.relativeToFile) : null;
280505
280928
  function read2(uri, encoding) {
280506
280929
  return resolveUri(uri).then(function(path53) {
280507
280930
  return readFile3(path53, encoding).caught(function(error) {
@@ -288423,8 +288846,8 @@ var require_xlsx = __commonJS({
288423
288846
  }
288424
288847
  return L.length - R.length;
288425
288848
  }
288426
- function dirname10(p) {
288427
- if (p.charAt(p.length - 1) == "/") return p.slice(0, -1).indexOf("/") === -1 ? p : dirname10(p.slice(0, -1));
288849
+ function dirname11(p) {
288850
+ if (p.charAt(p.length - 1) == "/") return p.slice(0, -1).indexOf("/") === -1 ? p : dirname11(p.slice(0, -1));
288428
288851
  var c = p.lastIndexOf("/");
288429
288852
  return c === -1 ? p : p.slice(0, c + 1);
288430
288853
  }
@@ -288845,7 +289268,7 @@ var require_xlsx = __commonJS({
288845
289268
  data.push([cfb.FullPaths[i2], cfb.FileIndex[i2]]);
288846
289269
  }
288847
289270
  for (i2 = 0; i2 < data.length; ++i2) {
288848
- var dad = dirname10(data[i2][0]);
289271
+ var dad = dirname11(data[i2][0]);
288849
289272
  s = fullPaths[dad];
288850
289273
  if (!s) {
288851
289274
  data.push([dad, {
@@ -288881,13 +289304,13 @@ var require_xlsx = __commonJS({
288881
289304
  elt.size = 0;
288882
289305
  elt.type = 5;
288883
289306
  } else if (nm.slice(-1) == "/") {
288884
- for (j = i2 + 1; j < data.length; ++j) if (dirname10(cfb.FullPaths[j]) == nm) break;
289307
+ for (j = i2 + 1; j < data.length; ++j) if (dirname11(cfb.FullPaths[j]) == nm) break;
288885
289308
  elt.C = j >= data.length ? -1 : j;
288886
- for (j = i2 + 1; j < data.length; ++j) if (dirname10(cfb.FullPaths[j]) == dirname10(nm)) break;
289309
+ for (j = i2 + 1; j < data.length; ++j) if (dirname11(cfb.FullPaths[j]) == dirname11(nm)) break;
288887
289310
  elt.R = j >= data.length ? -1 : j;
288888
289311
  elt.type = 1;
288889
289312
  } else {
288890
- if (dirname10(cfb.FullPaths[i2 + 1] || "") == dirname10(nm)) elt.R = i2 + 1;
289313
+ if (dirname11(cfb.FullPaths[i2 + 1] || "") == dirname11(nm)) elt.R = i2 + 1;
288891
289314
  elt.type = 2;
288892
289315
  }
288893
289316
  }
@@ -350842,7 +351265,7 @@ ${fileList}`,
350842
351265
  let errorMessage = `\u274C Search content not found in file: ${filePath}
350843
351266
 
350844
351267
  `;
350845
- errorMessage += `\u{1F50D} Using smart fuzzy matching (threshold: 60%)
351268
+ errorMessage += `\u{1F50D} Using smart fuzzy matching (threshold: ${threshold})
350846
351269
  `;
350847
351270
  if (isOverEscaped(searchContent)) {
350848
351271
  errorMessage += `\u26A0\uFE0F Detected over-escaped content, automatic fix attempted but failed
@@ -351388,7 +351811,7 @@ ${formattedDiagnostics}`;
351388
351811
  },
351389
351812
  {
351390
351813
  name: "filesystem-edit_search",
351391
- description: 'RECOMMENDED for most edits: Search-and-replace with SMART FUZZY MATCHING. **CRITICAL PATH REQUIREMENTS**: (1) filePath parameter is REQUIRED - MUST be a valid non-empty string or array, never use undefined/null/empty string, (2) Use EXACT file paths from search results or user input - never use placeholders like "path/to/file", (3) If uncertain about path, use search tools first to find the correct file. **SUPPORTS BATCH EDITING**: Pass (1) single file with search/replace, (2) array of file paths with unified search/replace, or (3) array of {path, searchContent, replaceContent, occurrence?} for per-file edits. **CRITICAL WORKFLOW FOR CODE SAFETY**: (1) Use search tools (codebase-search or ACE tools) to locate code, (2) MUST use filesystem-read to identify COMPLETE code boundaries (entire function body with all braces, complete markup tags with opening/closing pairs, full code blocks), (3) Copy the COMPLETE code block (without line numbers), (4) Verify boundaries are intact (matching braces/brackets/tags), (5) Use THIS tool. **WHY USE THIS**: No line tracking needed, auto-handles spacing/tabs differences, finds best fuzzy match even with whitespace changes, safer than line-based editing. **SMART MATCHING**: Uses similarity algorithm (60% threshold) to find code even if indentation/spacing differs from your search string. Automatically corrects over-escaped content. If multiple matches found, selects best match first (highest similarity score). **COMMON ERRORS TO AVOID**: Using invalid/empty file paths, modifying only part of a function (missing closing brace), incomplete markup tags (HTML/Vue/JSX), partial code blocks, copying line numbers from filesystem-read output. Always include complete syntactic units with all opening/closing pairs. **BATCH EXAMPLE**: filePath=[{path:"a.ts", searchContent:"old1", replaceContent:"new1"}, {path:"b.ts", searchContent:"old2", replaceContent:"new2"}]',
351814
+ description: 'RECOMMENDED for most edits: Search-and-replace with SMART FUZZY MATCHING. **CRITICAL PATH REQUIREMENTS**: (1) filePath parameter is REQUIRED - MUST be a valid non-empty string or array, never use undefined/null/empty string, (2) Use EXACT file paths from search results or user input - never use placeholders like "path/to/file", (3) If uncertain about path, use search tools first to find the correct file. **SUPPORTS BATCH EDITING**: Pass (1) single file with search/replace, (2) array of file paths with unified search/replace, or (3) array of {path, searchContent, replaceContent, occurrence?} for per-file edits. **CRITICAL WORKFLOW FOR CODE SAFETY - COMPLETE BOUNDARIES REQUIRED**: (1) Use search tools (codebase-search or ACE tools) to locate code, (2) MUST use filesystem-read to identify COMPLETE code boundaries with ALL closing pairs: entire function from declaration to final closing brace `}`, complete HTML/XML/JSX tags from opening `<tag>` to closing `</tag>`, full code blocks with ALL matching brackets/braces/parentheses, (3) Copy the COMPLETE code block (without line numbers) - verify you have captured ALL opening and closing symbols, (4) MANDATORY verification: Count and match ALL pairs - every `{` must have `}`, every `(` must have `)`, every `[` must have `]`, every `<tag>` must have `</tag>`, (5) Use THIS tool only after verification passes. **ABSOLUTE PROHIBITIONS**: NEVER edit partial functions (missing closing brace), NEVER edit incomplete markup (missing closing tag), NEVER edit partial code blocks (unmatched brackets), NEVER copy line numbers from filesystem-read output. **WHY USE THIS**: No line tracking needed, auto-handles spacing/tabs differences, finds best fuzzy match even with whitespace changes, safer than line-based editing. **SMART MATCHING**: Uses similarity algorithm to find code even if indentation/spacing differs from your search string. Automatically corrects over-escaped content. If multiple matches found, selects best match first (highest similarity score). **COMMON FATAL ERRORS TO AVOID**: Using invalid/empty file paths, modifying only part of a function (missing closing brace `}`), incomplete markup tags (HTML/Vue/JSX missing `</tag>`), partial code blocks (unmatched `{`, `}`, `(`, `)`, `[`, `]`), copying line numbers from filesystem-read output. You MUST include complete syntactic units with ALL opening/closing pairs verified and matched. **BATCH EXAMPLE**: filePath=[{path:"a.ts", searchContent:"old1", replaceContent:"new1"}, {path:"b.ts", searchContent:"old2", replaceContent:"new2"}]',
351392
351815
  inputSchema: {
351393
351816
  type: "object",
351394
351817
  properties: {
@@ -351458,7 +351881,7 @@ ${formattedDiagnostics}`;
351458
351881
  },
351459
351882
  {
351460
351883
  name: "filesystem-edit",
351461
- description: 'Line-based editing for precise control. **CRITICAL PATH REQUIREMENTS**: (1) filePath parameter is REQUIRED - MUST be a valid non-empty string or array, never use undefined/null/empty string, (2) Use EXACT file paths from search results or user input - never use placeholders like "path/to/file", (3) If uncertain about path, use search tools first to find the correct file. **SUPPORTS BATCH EDITING**: Pass (1) single file with line range, (2) array of file paths with unified line range, or (3) array of {path, startLine, endLine, newContent} for per-file edits. **WHEN TO USE**: (1) Adding new code sections, (2) Deleting specific line ranges, (3) When search-replace not suitable. **CRITICAL WORKFLOW FOR CODE SAFETY**: (1) Use search tools (codebase-search or ACE tools) to locate area, (2) MUST use filesystem-read to identify COMPLETE code boundaries - for functions: include opening line to closing brace; for markup tags (HTML/Vue/JSX): include opening tag to closing tag; for code blocks: include all braces/brackets, (3) Verify line range covers the ENTIRE syntactic unit (check indentation levels, matching pairs), (4) Use THIS tool with exact startLine/endLine. **BEST PRACTICE**: Keep edits small (under 15 lines recommended) for better accuracy. For larger changes, make multiple parallel edits to non-overlapping sections instead of one large edit. **RECOMMENDATION**: For modifying existing code, use filesystem-edit_search - safer and no line tracking needed. **WHY LINE-BASED IS RISKIER**: Line numbers can shift during editing, making it easy to target wrong lines. Search-replace avoids this by matching actual content. **COMMON ERRORS TO AVOID**: Using invalid/empty file paths, line range stops mid-function (missing closing brace), partial markup tags, incomplete code blocks, targeting wrong lines after file changes. Always verify boundaries with filesystem-read first. **BATCH EXAMPLE**: filePath=[{path:"a.ts", startLine:10, endLine:20, newContent:"..."}, {path:"b.ts", startLine:50, endLine:60, newContent:"..."}]',
351884
+ description: 'Line-based editing for precise control. **CRITICAL PATH REQUIREMENTS**: (1) filePath parameter is REQUIRED - MUST be a valid non-empty string or array, never use undefined/null/empty string, (2) Use EXACT file paths from search results or user input - never use placeholders like "path/to/file", (3) If uncertain about path, use search tools first to find the correct file. **SUPPORTS BATCH EDITING**: Pass (1) single file with line range, (2) array of file paths with unified line range, or (3) array of {path, startLine, endLine, newContent} for per-file edits. **WHEN TO USE**: (1) Adding new code sections, (2) Deleting specific line ranges, (3) When search-replace not suitable. **CRITICAL WORKFLOW FOR CODE SAFETY - COMPLETE BOUNDARIES REQUIRED**: (1) Use search tools (codebase-search or ACE tools) to locate area, (2) MUST use filesystem-read to identify COMPLETE code boundaries with ALL closing pairs: for functions - include opening declaration to final closing brace `}`; for HTML/XML/JSX markup tags - include opening `<tag>` to closing `</tag>`; for code blocks - include ALL matching braces/brackets/parentheses, (3) MANDATORY verification before editing: count opening and closing symbols in your target range - every `{` must have matching `}`, every `(` must have `)`, every `[` must have `]`, every `<tag>` must have `</tag>`, verify indentation levels are consistent, (4) Use THIS tool with exact startLine/endLine ONLY after verification passes. **ABSOLUTE PROHIBITIONS**: NEVER edit line range that stops mid-function (missing closing brace `}`), NEVER edit partial markup tags (missing `</tag>`), NEVER edit incomplete code blocks (unmatched brackets), NEVER edit without verifying boundaries first. **BEST PRACTICE**: Keep edits small (under 15 lines recommended) for better accuracy. For larger changes, make multiple parallel edits to non-overlapping sections instead of one large edit. **RECOMMENDATION**: For modifying existing code, use filesystem-edit_search - safer and no line tracking needed. **WHY LINE-BASED IS RISKIER**: Line numbers can shift during editing, making it easy to target wrong lines. Search-replace avoids this by matching actual content. **COMMON FATAL ERRORS TO AVOID**: Using invalid/empty file paths, line range stops mid-function (missing closing brace `}`), partial markup tags (missing `</tag>`), incomplete code blocks (unmatched `{`, `}`, `(`, `)`, `[`, `]`), targeting wrong lines after file changes, not verifying boundaries with filesystem-read first. You MUST verify complete syntactic units with ALL opening/closing pairs matched. **BATCH EXAMPLE**: filePath=[{path:"a.ts", startLine:10, endLine:20, newContent:"..."}, {path:"b.ts", startLine:50, endLine:60, newContent:"..."}]',
351462
351885
  inputSchema: {
351463
351886
  type: "object",
351464
351887
  properties: {
@@ -403920,7 +404343,7 @@ var require_util12 = __commonJS({
403920
404343
  exports2.isAbsolute = function(aPath) {
403921
404344
  return aPath.charAt(0) === "/" || urlRegexp.test(aPath);
403922
404345
  };
403923
- function relative8(aRoot, aPath) {
404346
+ function relative9(aRoot, aPath) {
403924
404347
  if (aRoot === "") {
403925
404348
  aRoot = ".";
403926
404349
  }
@@ -403939,7 +404362,7 @@ var require_util12 = __commonJS({
403939
404362
  }
403940
404363
  return Array(level + 1).join("../") + aPath.substr(aRoot.length + 1);
403941
404364
  }
403942
- exports2.relative = relative8;
404365
+ exports2.relative = relative9;
403943
404366
  var supportsNullProto = (function() {
403944
404367
  var obj2 = /* @__PURE__ */ Object.create(null);
403945
404368
  return !("__proto__" in obj2);
@@ -435993,7 +436416,7 @@ var require_gray_matter = __commonJS({
435993
436416
  });
435994
436417
 
435995
436418
  // dist/mcp/skills.js
435996
- import { join as join21 } from "path";
436419
+ import { dirname as dirname8, join as join21, relative as relative6 } from "path";
435997
436420
  import { existsSync as existsSync21 } from "fs";
435998
436421
  import { readFile as readFile2 } from "fs/promises";
435999
436422
  import { homedir as homedir14 } from "os";
@@ -436032,64 +436455,75 @@ async function readSkillFile(skillPath) {
436032
436455
  return null;
436033
436456
  }
436034
436457
  }
436035
- async function loadAvailableSkills(projectRoot) {
436036
- const skills = /* @__PURE__ */ new Map();
436037
- const globalSkillsDir = join21(homedir14(), ".snow", "skills");
436038
- const projectSkillsDir = projectRoot ? join21(projectRoot, ".snow", "skills") : null;
436039
- if (existsSync21(globalSkillsDir)) {
436040
- try {
436041
- const { readdirSync: readdirSync3 } = await import("fs");
436042
- const entries = readdirSync3(globalSkillsDir, { withFileTypes: true });
436043
- for (const entry of entries) {
436044
- if (entry.isDirectory()) {
436045
- const skillPath = join21(globalSkillsDir, entry.name);
436046
- const skillData = await readSkillFile(skillPath);
436047
- if (skillData) {
436048
- skills.set(entry.name, {
436049
- name: skillData.metadata.name || entry.name,
436050
- description: skillData.metadata.description || "",
436051
- location: "global",
436052
- path: skillPath,
436053
- content: skillData.content,
436054
- allowedTools: skillData.metadata.allowedTools
436055
- });
436056
- }
436057
- }
436058
- }
436059
- } catch (error) {
436060
- console.error("Failed to load global skills:", error);
436061
- }
436458
+ function normalizeSkillId(skillId) {
436459
+ return skillId.replace(/\\/g, "/").replace(/^\.\/+/, "");
436460
+ }
436461
+ async function loadSkillsFromDirectory(skills, baseSkillsDir, location) {
436462
+ if (!existsSync21(baseSkillsDir)) {
436463
+ return;
436062
436464
  }
436063
- if (projectSkillsDir && existsSync21(projectSkillsDir)) {
436064
- try {
436065
- const { readdirSync: readdirSync3 } = await import("fs");
436066
- const entries = readdirSync3(projectSkillsDir, { withFileTypes: true });
436465
+ try {
436466
+ const { readdirSync: readdirSync3 } = await import("fs");
436467
+ const pendingDirs = [baseSkillsDir];
436468
+ while (pendingDirs.length > 0) {
436469
+ const currentDir = pendingDirs.pop();
436470
+ if (!currentDir)
436471
+ continue;
436472
+ let entries;
436473
+ try {
436474
+ entries = readdirSync3(currentDir, { withFileTypes: true });
436475
+ } catch {
436476
+ continue;
436477
+ }
436067
436478
  for (const entry of entries) {
436068
436479
  if (entry.isDirectory()) {
436069
- const skillPath = join21(projectSkillsDir, entry.name);
436070
- const skillData = await readSkillFile(skillPath);
436071
- if (skillData) {
436072
- skills.set(entry.name, {
436073
- name: skillData.metadata.name || entry.name,
436074
- description: skillData.metadata.description || "",
436075
- location: "project",
436076
- path: skillPath,
436077
- content: skillData.content,
436078
- allowedTools: skillData.metadata.allowedTools
436079
- });
436080
- }
436480
+ pendingDirs.push(join21(currentDir, entry.name));
436481
+ continue;
436482
+ }
436483
+ if (!entry.isFile() || entry.name !== "SKILL.md") {
436484
+ continue;
436081
436485
  }
436486
+ const skillFile = join21(currentDir, entry.name);
436487
+ const skillDir = dirname8(skillFile);
436488
+ const rawSkillId = relative6(baseSkillsDir, skillDir);
436489
+ const skillId = normalizeSkillId(rawSkillId);
436490
+ if (!skillId || skillId === ".") {
436491
+ continue;
436492
+ }
436493
+ const skillData = await readSkillFile(skillDir);
436494
+ if (!skillData) {
436495
+ continue;
436496
+ }
436497
+ const fallbackName = skillId.split("/").filter(Boolean).pop() || skillId;
436498
+ skills.set(skillId, {
436499
+ id: skillId,
436500
+ name: skillData.metadata.name || fallbackName,
436501
+ description: skillData.metadata.description || "",
436502
+ location,
436503
+ path: skillDir,
436504
+ content: skillData.content,
436505
+ allowedTools: skillData.metadata.allowedTools
436506
+ });
436082
436507
  }
436083
- } catch (error) {
436084
- console.error("Failed to load project skills:", error);
436085
436508
  }
436509
+ } catch (error) {
436510
+ console.error(`Failed to load ${location} skills:`, error);
436511
+ }
436512
+ }
436513
+ async function loadAvailableSkills(projectRoot) {
436514
+ const skills = /* @__PURE__ */ new Map();
436515
+ const globalSkillsDir = join21(homedir14(), ".snow", "skills");
436516
+ const projectSkillsDir = projectRoot ? join21(projectRoot, ".snow", "skills") : null;
436517
+ await loadSkillsFromDirectory(skills, globalSkillsDir, "global");
436518
+ if (projectSkillsDir) {
436519
+ await loadSkillsFromDirectory(skills, projectSkillsDir, "project");
436086
436520
  }
436087
436521
  return skills;
436088
436522
  }
436089
436523
  function generateSkillToolDescription(skills) {
436090
436524
  const skillsList = Array.from(skills.values()).map((skill) => `<skill>
436091
436525
  <name>
436092
- ${skill.name}
436526
+ ${skill.id}
436093
436527
  </name>
436094
436528
  <description>
436095
436529
  ${skill.description}
@@ -436104,7 +436538,7 @@ ${skill.location}
436104
436538
  When users ask you to perform tasks, check if any of the available skills below can help complete the task more effectively. Skills provide specialized capabilities and domain knowledge.
436105
436539
 
436106
436540
  How to use skills:
436107
- - Invoke skills using this tool with the skill name only (no arguments)
436541
+ - Invoke skills using this tool with the skill id only (no arguments)
436108
436542
  - When you invoke a skill, you will see <command-message>The "{name}" skill is loading</command-message>
436109
436543
  - The skill's prompt will expand and provide detailed instructions on how to complete the task
436110
436544
  - Examples:
@@ -436136,7 +436570,7 @@ async function getMCPTools2(projectRoot) {
436136
436570
  properties: {
436137
436571
  skill: {
436138
436572
  type: "string",
436139
- description: 'The skill name (no arguments). E.g., "pdf" or "data-analysis"'
436573
+ description: 'The skill id (no arguments). E.g., "pdf", "data-analysis", or "helloagents/analyze"'
436140
436574
  }
436141
436575
  },
436142
436576
  required: ["skill"],
@@ -436196,15 +436630,16 @@ async function executeSkillTool(toolName, args2, projectRoot) {
436196
436630
  if (toolName !== "skill-execute") {
436197
436631
  throw new Error(`Unknown tool: ${toolName}`);
436198
436632
  }
436199
- const skillName = args2.skill;
436200
- if (!skillName || typeof skillName !== "string") {
436633
+ const requestedSkillId = args2.skill;
436634
+ if (!requestedSkillId || typeof requestedSkillId !== "string") {
436201
436635
  throw new Error("skill parameter is required and must be a string");
436202
436636
  }
436637
+ const skillId = normalizeSkillId(requestedSkillId);
436203
436638
  const skills = await loadAvailableSkills(projectRoot);
436204
- const skill = skills.get(skillName);
436639
+ const skill = skills.get(skillId);
436205
436640
  if (!skill) {
436206
436641
  const availableSkills = Array.from(skills.keys()).join(", ");
436207
- throw new Error(`Skill "${skillName}" not found. Available skills: ${availableSkills || "none"}`);
436642
+ throw new Error(`Skill "${skillId}" not found. Available skills: ${availableSkills || "none"}`);
436208
436643
  }
436209
436644
  const directoryTree = await generateSkillTree(skill.path);
436210
436645
  let toolRestriction = "";
@@ -543962,6 +544397,7 @@ var init_SkillsCreationPanel = __esm({
543962
544397
  "use strict";
543963
544398
  import_react115 = __toESM(require_react(), 1);
543964
544399
  await init_build2();
544400
+ await init_build3();
543965
544401
  await init_build4();
543966
544402
  init_ThemeContext();
543967
544403
  init_I18nContext();
@@ -543969,16 +544405,145 @@ var init_SkillsCreationPanel = __esm({
543969
544405
  SkillsCreationPanel = ({ onSave, onCancel, projectRoot }) => {
543970
544406
  const { theme: theme14 } = useTheme();
543971
544407
  const { t } = useI18n();
543972
- const [step, setStep] = (0, import_react115.useState)("name");
544408
+ const [step, setStep] = (0, import_react115.useState)("mode");
544409
+ const [mode, setMode] = (0, import_react115.useState)("manual");
543973
544410
  const [skillName, setSkillName] = (0, import_react115.useState)("");
543974
544411
  const [description, setDescription] = (0, import_react115.useState)("");
543975
544412
  const [location, setLocation] = (0, import_react115.useState)("global");
544413
+ const [requirement, setRequirement] = (0, import_react115.useState)("");
544414
+ const [generated, setGenerated] = (0, import_react115.useState)();
543976
544415
  const [errorMessage, setErrorMessage] = (0, import_react115.useState)("");
544416
+ const abortControllerRef = (0, import_react115.useRef)(null);
544417
+ const handleCancel = (0, import_react115.useCallback)(() => {
544418
+ var _a21;
544419
+ try {
544420
+ (_a21 = abortControllerRef.current) == null ? void 0 : _a21.abort();
544421
+ } catch {
544422
+ }
544423
+ onCancel();
544424
+ }, [onCancel]);
544425
+ const handleNameSubmit = (0, import_react115.useCallback)((value) => {
544426
+ if (!value.trim()) {
544427
+ return;
544428
+ }
544429
+ const trimmedName = value.trim();
544430
+ const validation = validateSkillId(trimmedName);
544431
+ if (!validation.valid) {
544432
+ setErrorMessage(validation.error || t.skillsCreation.errorInvalidName);
544433
+ return;
544434
+ }
544435
+ const existsGlobal = checkSkillExists(trimmedName, "global");
544436
+ const existsProject = checkSkillExists(trimmedName, "project", projectRoot);
544437
+ if (existsGlobal && existsProject) {
544438
+ setErrorMessage(t.skillsCreation.errorExistsBoth.replace("{name}", trimmedName));
544439
+ return;
544440
+ }
544441
+ if (existsGlobal) {
544442
+ setErrorMessage(t.skillsCreation.errorExistsGlobal.replace("{name}", trimmedName));
544443
+ return;
544444
+ }
544445
+ if (existsProject) {
544446
+ setErrorMessage(t.skillsCreation.errorExistsProject.replace("{name}", trimmedName));
544447
+ return;
544448
+ }
544449
+ setErrorMessage("");
544450
+ setSkillName(trimmedName);
544451
+ setStep("description");
544452
+ }, [projectRoot, t.skillsCreation]);
544453
+ const handleDescriptionSubmit = (0, import_react115.useCallback)((value) => {
544454
+ if (value.trim()) {
544455
+ setDescription(value.trim());
544456
+ setStep("location");
544457
+ }
544458
+ }, []);
544459
+ const handleRequirementSubmit = (0, import_react115.useCallback)((value) => {
544460
+ if (value.trim()) {
544461
+ setRequirement(value.trim());
544462
+ setErrorMessage("");
544463
+ setStep("ai-location");
544464
+ }
544465
+ }, []);
544466
+ const handleConfirmManual = (0, import_react115.useCallback)(async () => {
544467
+ await onSave(skillName, description, location);
544468
+ }, [skillName, description, location, onSave]);
544469
+ const handleConfirmAI = (0, import_react115.useCallback)(async () => {
544470
+ if (!generated) {
544471
+ setErrorMessage(t.skillsCreation.errorNoGeneratedContent);
544472
+ return;
544473
+ }
544474
+ await onSave(skillName, description, location, generated);
544475
+ }, [generated, skillName, description, location, onSave, t.skillsCreation]);
544476
+ const handleEditNameSubmit = (0, import_react115.useCallback)((value) => {
544477
+ if (!value.trim()) {
544478
+ return;
544479
+ }
544480
+ const trimmedName = value.trim();
544481
+ const validation = validateSkillId(trimmedName);
544482
+ if (!validation.valid) {
544483
+ setErrorMessage(validation.error || t.skillsCreation.errorInvalidName);
544484
+ return;
544485
+ }
544486
+ const existsGlobal = checkSkillExists(trimmedName, "global");
544487
+ const existsProject = checkSkillExists(trimmedName, "project", projectRoot);
544488
+ if (existsGlobal || existsProject) {
544489
+ setErrorMessage(t.skillsCreation.errorExistsAny.replace("{name}", trimmedName));
544490
+ return;
544491
+ }
544492
+ setErrorMessage("");
544493
+ setSkillName(trimmedName);
544494
+ setStep("ai-preview");
544495
+ }, [projectRoot, t.skillsCreation]);
544496
+ (0, import_react115.useEffect)(() => {
544497
+ if (step !== "ai-generating") {
544498
+ return;
544499
+ }
544500
+ const controller = new AbortController();
544501
+ abortControllerRef.current = controller;
544502
+ setErrorMessage("");
544503
+ setGenerated(void 0);
544504
+ generateSkillDraftWithAI(requirement, projectRoot, controller.signal).then((draft) => {
544505
+ setSkillName(draft.skillName);
544506
+ setDescription(draft.description);
544507
+ setGenerated(draft.generated);
544508
+ setStep("ai-preview");
544509
+ }).catch((error) => {
544510
+ if (controller.signal.aborted) {
544511
+ return;
544512
+ }
544513
+ const message = error instanceof Error ? error.message : t.skillsCreation.errorGeneration;
544514
+ setErrorMessage(message);
544515
+ setStep("ai-error");
544516
+ }).finally(() => {
544517
+ abortControllerRef.current = null;
544518
+ });
544519
+ return () => {
544520
+ try {
544521
+ controller.abort();
544522
+ } catch {
544523
+ }
544524
+ };
544525
+ }, [step, requirement, projectRoot, t.skillsCreation.errorGeneration]);
544526
+ const keyHandlingActive = step === "mode" || step === "location" || step === "confirm" || step === "ai-location" || step === "ai-generating" || step === "ai-preview" || step === "ai-error";
543977
544527
  use_input_default((input2, key) => {
543978
544528
  if (key.escape) {
543979
544529
  handleCancel();
543980
544530
  return;
543981
544531
  }
544532
+ if (step === "mode") {
544533
+ if (input2.toLowerCase() === "m") {
544534
+ setMode("manual");
544535
+ setErrorMessage("");
544536
+ setStep("name");
544537
+ } else if (input2.toLowerCase() === "a") {
544538
+ setMode("ai");
544539
+ setErrorMessage("");
544540
+ setSkillName("");
544541
+ setDescription("");
544542
+ setGenerated(void 0);
544543
+ setStep("ai-requirement");
544544
+ }
544545
+ return;
544546
+ }
543982
544547
  if (step === "location") {
543983
544548
  if (input2.toLowerCase() === "g") {
543984
544549
  setLocation("global");
@@ -543987,51 +544552,45 @@ var init_SkillsCreationPanel = __esm({
543987
544552
  setLocation("project");
543988
544553
  setStep("confirm");
543989
544554
  }
543990
- } else if (step === "confirm") {
544555
+ return;
544556
+ }
544557
+ if (step === "confirm") {
543991
544558
  if (input2.toLowerCase() === "y") {
543992
- handleConfirm();
544559
+ handleConfirmManual();
543993
544560
  } else if (input2.toLowerCase() === "n") {
543994
544561
  handleCancel();
543995
544562
  }
544563
+ return;
543996
544564
  }
543997
- }, { isActive: step === "location" || step === "confirm" });
543998
- const handleNameSubmit = (0, import_react115.useCallback)((value) => {
543999
- if (value.trim()) {
544000
- const trimmedName = value.trim();
544001
- const validation = validateSkillName(trimmedName);
544002
- if (!validation.valid) {
544003
- setErrorMessage(validation.error || t.skillsCreation.errorInvalidName);
544004
- return;
544565
+ if (step === "ai-location") {
544566
+ if (input2.toLowerCase() === "g") {
544567
+ setLocation("global");
544568
+ setStep("ai-generating");
544569
+ } else if (input2.toLowerCase() === "p") {
544570
+ setLocation("project");
544571
+ setStep("ai-generating");
544005
544572
  }
544006
- const existsGlobal = checkSkillExists(trimmedName, "global");
544007
- const existsProject = checkSkillExists(trimmedName, "project", projectRoot);
544008
- if (existsGlobal && existsProject) {
544009
- setErrorMessage(t.skillsCreation.errorExistsBoth.replace("{name}", trimmedName));
544010
- return;
544011
- } else if (existsGlobal) {
544012
- setErrorMessage(t.skillsCreation.errorExistsGlobal.replace("{name}", trimmedName));
544013
- return;
544014
- } else if (existsProject) {
544015
- setErrorMessage(t.skillsCreation.errorExistsProject.replace("{name}", trimmedName));
544016
- return;
544573
+ return;
544574
+ }
544575
+ if (step === "ai-preview") {
544576
+ if (input2.toLowerCase() === "y") {
544577
+ handleConfirmAI();
544578
+ } else if (input2.toLowerCase() === "e") {
544579
+ setErrorMessage("");
544580
+ setStep("ai-edit-name");
544581
+ } else if (input2.toLowerCase() === "r") {
544582
+ setErrorMessage("");
544583
+ setStep("ai-generating");
544017
544584
  }
544018
- setErrorMessage("");
544019
- setSkillName(trimmedName);
544020
- setStep("description");
544585
+ return;
544021
544586
  }
544022
- }, [projectRoot, t.skillsCreation]);
544023
- const handleDescriptionSubmit = (0, import_react115.useCallback)((value) => {
544024
- if (value.trim()) {
544025
- setDescription(value.trim());
544026
- setStep("location");
544587
+ if (step === "ai-error") {
544588
+ if (input2.toLowerCase() === "r") {
544589
+ setErrorMessage("");
544590
+ setStep("ai-generating");
544591
+ }
544027
544592
  }
544028
- }, []);
544029
- const handleConfirm = (0, import_react115.useCallback)(async () => {
544030
- await onSave(skillName, description, location);
544031
- }, [skillName, description, location, onSave]);
544032
- const handleCancel = (0, import_react115.useCallback)(() => {
544033
- onCancel();
544034
- }, [onCancel]);
544593
+ }, { isActive: keyHandlingActive });
544035
544594
  return import_react115.default.createElement(
544036
544595
  Box_default,
544037
544596
  { flexDirection: "column", padding: 1, borderStyle: "round", borderColor: theme14.colors.border },
@@ -544040,7 +544599,47 @@ var init_SkillsCreationPanel = __esm({
544040
544599
  { marginBottom: 1 },
544041
544600
  import_react115.default.createElement(Text, { bold: true, color: theme14.colors.menuSelected }, t.skillsCreation.title)
544042
544601
  ),
544043
- step === "name" && import_react115.default.createElement(
544602
+ step === "mode" && import_react115.default.createElement(
544603
+ Box_default,
544604
+ { flexDirection: "column" },
544605
+ import_react115.default.createElement(
544606
+ Box_default,
544607
+ { marginBottom: 1 },
544608
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.modeLabel)
544609
+ ),
544610
+ import_react115.default.createElement(
544611
+ Box_default,
544612
+ { gap: 2 },
544613
+ import_react115.default.createElement(
544614
+ Box_default,
544615
+ null,
544616
+ import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[A]"),
544617
+ import_react115.default.createElement(
544618
+ Text,
544619
+ { color: theme14.colors.text },
544620
+ " ",
544621
+ t.skillsCreation.modeAi
544622
+ )
544623
+ ),
544624
+ import_react115.default.createElement(
544625
+ Box_default,
544626
+ null,
544627
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[M]"),
544628
+ import_react115.default.createElement(
544629
+ Text,
544630
+ { color: theme14.colors.text },
544631
+ " ",
544632
+ t.skillsCreation.modeManual
544633
+ )
544634
+ )
544635
+ ),
544636
+ import_react115.default.createElement(
544637
+ Box_default,
544638
+ { marginTop: 1 },
544639
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544640
+ )
544641
+ ),
544642
+ mode === "manual" && step === "name" && import_react115.default.createElement(
544044
544643
  Box_default,
544045
544644
  { flexDirection: "column" },
544046
544645
  import_react115.default.createElement(
@@ -544065,7 +544664,7 @@ var init_SkillsCreationPanel = __esm({
544065
544664
  import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544066
544665
  )
544067
544666
  ),
544068
- step === "description" && import_react115.default.createElement(
544667
+ mode === "manual" && step === "description" && import_react115.default.createElement(
544069
544668
  Box_default,
544070
544669
  { flexDirection: "column" },
544071
544670
  import_react115.default.createElement(
@@ -544096,7 +544695,293 @@ var init_SkillsCreationPanel = __esm({
544096
544695
  import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544097
544696
  )
544098
544697
  ),
544099
- step === "location" && import_react115.default.createElement(
544698
+ mode === "manual" && step === "location" && import_react115.default.createElement(
544699
+ Box_default,
544700
+ { flexDirection: "column" },
544701
+ import_react115.default.createElement(
544702
+ Box_default,
544703
+ { marginBottom: 1 },
544704
+ import_react115.default.createElement(
544705
+ Text,
544706
+ { color: theme14.colors.text },
544707
+ t.skillsCreation.nameLabel,
544708
+ " ",
544709
+ import_react115.default.createElement(Text, { bold: true, color: theme14.colors.success }, skillName)
544710
+ )
544711
+ ),
544712
+ import_react115.default.createElement(
544713
+ Box_default,
544714
+ { marginBottom: 1 },
544715
+ import_react115.default.createElement(
544716
+ Text,
544717
+ { color: theme14.colors.text },
544718
+ t.skillsCreation.descriptionLabel,
544719
+ " ",
544720
+ import_react115.default.createElement(Text, { color: theme14.colors.menuNormal }, description)
544721
+ )
544722
+ ),
544723
+ import_react115.default.createElement(
544724
+ Box_default,
544725
+ { marginBottom: 1, marginTop: 1 },
544726
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.locationLabel)
544727
+ ),
544728
+ import_react115.default.createElement(
544729
+ Box_default,
544730
+ { marginTop: 1, flexDirection: "column", gap: 1 },
544731
+ import_react115.default.createElement(
544732
+ Box_default,
544733
+ null,
544734
+ import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[G]"),
544735
+ import_react115.default.createElement(
544736
+ Text,
544737
+ { color: theme14.colors.text },
544738
+ " ",
544739
+ t.skillsCreation.locationGlobal
544740
+ )
544741
+ ),
544742
+ import_react115.default.createElement(
544743
+ Box_default,
544744
+ { marginLeft: 4 },
544745
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationGlobalInfo)
544746
+ ),
544747
+ import_react115.default.createElement(
544748
+ Box_default,
544749
+ { marginTop: 1 },
544750
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[P]"),
544751
+ import_react115.default.createElement(
544752
+ Text,
544753
+ { color: theme14.colors.text },
544754
+ " ",
544755
+ t.skillsCreation.locationProject
544756
+ )
544757
+ ),
544758
+ import_react115.default.createElement(
544759
+ Box_default,
544760
+ { marginLeft: 4 },
544761
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationProjectInfo)
544762
+ )
544763
+ ),
544764
+ import_react115.default.createElement(
544765
+ Box_default,
544766
+ { marginTop: 1 },
544767
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544768
+ )
544769
+ ),
544770
+ mode === "manual" && step === "confirm" && import_react115.default.createElement(
544771
+ Box_default,
544772
+ { flexDirection: "column" },
544773
+ import_react115.default.createElement(
544774
+ Box_default,
544775
+ { marginBottom: 1 },
544776
+ import_react115.default.createElement(
544777
+ Text,
544778
+ { color: theme14.colors.text },
544779
+ t.skillsCreation.nameLabel,
544780
+ " ",
544781
+ import_react115.default.createElement(Text, { bold: true, color: theme14.colors.success }, skillName)
544782
+ )
544783
+ ),
544784
+ import_react115.default.createElement(
544785
+ Box_default,
544786
+ { marginBottom: 1 },
544787
+ import_react115.default.createElement(
544788
+ Text,
544789
+ { color: theme14.colors.text },
544790
+ t.skillsCreation.descriptionLabel,
544791
+ " ",
544792
+ import_react115.default.createElement(Text, { color: theme14.colors.menuNormal }, description)
544793
+ )
544794
+ ),
544795
+ import_react115.default.createElement(
544796
+ Box_default,
544797
+ { marginBottom: 1 },
544798
+ import_react115.default.createElement(
544799
+ Text,
544800
+ { color: theme14.colors.text },
544801
+ t.skillsCreation.locationLabel,
544802
+ " ",
544803
+ import_react115.default.createElement(Text, { bold: true, color: theme14.colors.menuSelected }, location === "global" ? t.skillsCreation.locationGlobal : t.skillsCreation.locationProject)
544804
+ )
544805
+ ),
544806
+ import_react115.default.createElement(
544807
+ Box_default,
544808
+ { marginTop: 1 },
544809
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.confirmQuestion)
544810
+ ),
544811
+ import_react115.default.createElement(
544812
+ Box_default,
544813
+ { marginTop: 1, gap: 2 },
544814
+ import_react115.default.createElement(
544815
+ Box_default,
544816
+ null,
544817
+ import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[Y]"),
544818
+ import_react115.default.createElement(
544819
+ Text,
544820
+ { color: theme14.colors.text },
544821
+ " ",
544822
+ t.skillsCreation.confirmYes
544823
+ )
544824
+ ),
544825
+ import_react115.default.createElement(
544826
+ Box_default,
544827
+ null,
544828
+ import_react115.default.createElement(Text, { color: theme14.colors.error, bold: true }, "[N]"),
544829
+ import_react115.default.createElement(
544830
+ Text,
544831
+ { color: theme14.colors.text },
544832
+ " ",
544833
+ t.skillsCreation.confirmNo
544834
+ )
544835
+ )
544836
+ )
544837
+ ),
544838
+ mode === "ai" && step === "ai-requirement" && import_react115.default.createElement(
544839
+ Box_default,
544840
+ { flexDirection: "column" },
544841
+ import_react115.default.createElement(
544842
+ Box_default,
544843
+ { marginBottom: 1 },
544844
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.requirementLabel)
544845
+ ),
544846
+ import_react115.default.createElement(
544847
+ Box_default,
544848
+ { marginBottom: 1 },
544849
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.requirementHint)
544850
+ ),
544851
+ import_react115.default.createElement(TextInput, { placeholder: t.skillsCreation.requirementPlaceholder, onSubmit: handleRequirementSubmit }),
544852
+ import_react115.default.createElement(
544853
+ Box_default,
544854
+ { marginTop: 1 },
544855
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544856
+ )
544857
+ ),
544858
+ mode === "ai" && step === "ai-location" && import_react115.default.createElement(
544859
+ Box_default,
544860
+ { flexDirection: "column" },
544861
+ import_react115.default.createElement(
544862
+ Box_default,
544863
+ { marginBottom: 1 },
544864
+ import_react115.default.createElement(
544865
+ Text,
544866
+ { color: theme14.colors.text },
544867
+ t.skillsCreation.requirementLabel,
544868
+ " ",
544869
+ import_react115.default.createElement(Text, { color: theme14.colors.menuNormal }, requirement)
544870
+ )
544871
+ ),
544872
+ import_react115.default.createElement(
544873
+ Box_default,
544874
+ { marginBottom: 1, marginTop: 1 },
544875
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.locationLabel)
544876
+ ),
544877
+ import_react115.default.createElement(
544878
+ Box_default,
544879
+ { marginTop: 1, flexDirection: "column", gap: 1 },
544880
+ import_react115.default.createElement(
544881
+ Box_default,
544882
+ null,
544883
+ import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[G]"),
544884
+ import_react115.default.createElement(
544885
+ Text,
544886
+ { color: theme14.colors.text },
544887
+ " ",
544888
+ t.skillsCreation.locationGlobal
544889
+ )
544890
+ ),
544891
+ import_react115.default.createElement(
544892
+ Box_default,
544893
+ { marginLeft: 4 },
544894
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationGlobalInfo)
544895
+ ),
544896
+ import_react115.default.createElement(
544897
+ Box_default,
544898
+ { marginTop: 1 },
544899
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[P]"),
544900
+ import_react115.default.createElement(
544901
+ Text,
544902
+ { color: theme14.colors.text },
544903
+ " ",
544904
+ t.skillsCreation.locationProject
544905
+ )
544906
+ ),
544907
+ import_react115.default.createElement(
544908
+ Box_default,
544909
+ { marginLeft: 4 },
544910
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationProjectInfo)
544911
+ )
544912
+ ),
544913
+ import_react115.default.createElement(
544914
+ Box_default,
544915
+ { marginTop: 1 },
544916
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544917
+ )
544918
+ ),
544919
+ mode === "ai" && step === "ai-generating" && import_react115.default.createElement(
544920
+ Box_default,
544921
+ { flexDirection: "column" },
544922
+ import_react115.default.createElement(
544923
+ Box_default,
544924
+ { marginBottom: 1 },
544925
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.generatingLabel)
544926
+ ),
544927
+ import_react115.default.createElement(
544928
+ Box_default,
544929
+ null,
544930
+ import_react115.default.createElement(
544931
+ Text,
544932
+ { color: theme14.colors.menuNormal },
544933
+ import_react115.default.createElement(build_default, { type: "dots" }),
544934
+ " ",
544935
+ t.skillsCreation.generatingMessage
544936
+ )
544937
+ ),
544938
+ import_react115.default.createElement(
544939
+ Box_default,
544940
+ { marginTop: 1 },
544941
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544942
+ )
544943
+ ),
544944
+ mode === "ai" && step === "ai-error" && import_react115.default.createElement(
544945
+ Box_default,
544946
+ { flexDirection: "column" },
544947
+ import_react115.default.createElement(
544948
+ Box_default,
544949
+ { marginBottom: 1 },
544950
+ import_react115.default.createElement(Text, { color: theme14.colors.error }, t.skillsCreation.errorGeneration)
544951
+ ),
544952
+ errorMessage && import_react115.default.createElement(
544953
+ Box_default,
544954
+ { marginBottom: 1 },
544955
+ import_react115.default.createElement(Text, { color: theme14.colors.error }, errorMessage)
544956
+ ),
544957
+ import_react115.default.createElement(
544958
+ Box_default,
544959
+ { marginTop: 1, gap: 2 },
544960
+ import_react115.default.createElement(
544961
+ Box_default,
544962
+ null,
544963
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[R]"),
544964
+ import_react115.default.createElement(
544965
+ Text,
544966
+ { color: theme14.colors.text },
544967
+ " ",
544968
+ t.skillsCreation.regenerate
544969
+ )
544970
+ ),
544971
+ import_react115.default.createElement(
544972
+ Box_default,
544973
+ null,
544974
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSecondary, dimColor: true }, "[ESC]"),
544975
+ import_react115.default.createElement(
544976
+ Text,
544977
+ { color: theme14.colors.text },
544978
+ " ",
544979
+ t.skillsCreation.cancel
544980
+ )
544981
+ )
544982
+ )
544983
+ ),
544984
+ mode === "ai" && step === "ai-preview" && import_react115.default.createElement(
544100
544985
  Box_default,
544101
544986
  { flexDirection: "column" },
544102
544987
  import_react115.default.createElement(
@@ -544123,43 +545008,74 @@ var init_SkillsCreationPanel = __esm({
544123
545008
  ),
544124
545009
  import_react115.default.createElement(
544125
545010
  Box_default,
544126
- { marginBottom: 1, marginTop: 1 },
544127
- import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.locationLabel)
545011
+ { marginBottom: 1 },
545012
+ import_react115.default.createElement(
545013
+ Text,
545014
+ { color: theme14.colors.text },
545015
+ t.skillsCreation.locationLabel,
545016
+ " ",
545017
+ import_react115.default.createElement(Text, { bold: true, color: theme14.colors.menuSelected }, location === "global" ? t.skillsCreation.locationGlobal : t.skillsCreation.locationProject)
545018
+ )
544128
545019
  ),
544129
545020
  import_react115.default.createElement(
544130
545021
  Box_default,
544131
- { marginTop: 1, flexDirection: "column", gap: 1 },
545022
+ { marginTop: 1, flexDirection: "column" },
545023
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.filesLabel),
545024
+ import_react115.default.createElement(
545025
+ Box_default,
545026
+ { marginLeft: 2, flexDirection: "column" },
545027
+ import_react115.default.createElement(Text, { dimColor: true }, "- SKILL.md"),
545028
+ import_react115.default.createElement(Text, { dimColor: true }, "- reference.md"),
545029
+ import_react115.default.createElement(Text, { dimColor: true }, "- examples.md"),
545030
+ import_react115.default.createElement(Text, { dimColor: true }, "- templates/template.txt"),
545031
+ import_react115.default.createElement(Text, { dimColor: true }, "- scripts/helper.py")
545032
+ )
545033
+ ),
545034
+ errorMessage && import_react115.default.createElement(
545035
+ Box_default,
545036
+ { marginTop: 1 },
545037
+ import_react115.default.createElement(Text, { color: theme14.colors.error }, errorMessage)
545038
+ ),
545039
+ import_react115.default.createElement(
545040
+ Box_default,
545041
+ { marginTop: 1 },
545042
+ import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.confirmQuestion)
545043
+ ),
545044
+ import_react115.default.createElement(
545045
+ Box_default,
545046
+ { marginTop: 1, gap: 2 },
544132
545047
  import_react115.default.createElement(
544133
545048
  Box_default,
544134
545049
  null,
544135
- import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[G]"),
545050
+ import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[Y]"),
544136
545051
  import_react115.default.createElement(
544137
545052
  Text,
544138
545053
  { color: theme14.colors.text },
544139
545054
  " ",
544140
- t.skillsCreation.locationGlobal
545055
+ t.skillsCreation.confirmYes
544141
545056
  )
544142
545057
  ),
544143
545058
  import_react115.default.createElement(
544144
545059
  Box_default,
544145
- { marginLeft: 4 },
544146
- import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationGlobalInfo)
544147
- ),
544148
- import_react115.default.createElement(
544149
- Box_default,
544150
- { marginTop: 1 },
544151
- import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[P]"),
545060
+ null,
545061
+ import_react115.default.createElement(Text, { color: theme14.colors.menuSelected, bold: true }, "[E]"),
544152
545062
  import_react115.default.createElement(
544153
545063
  Text,
544154
545064
  { color: theme14.colors.text },
544155
545065
  " ",
544156
- t.skillsCreation.locationProject
545066
+ t.skillsCreation.editName
544157
545067
  )
544158
545068
  ),
544159
545069
  import_react115.default.createElement(
544160
545070
  Box_default,
544161
- { marginLeft: 4 },
544162
- import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.locationProjectInfo)
545071
+ null,
545072
+ import_react115.default.createElement(Text, { color: theme14.colors.warning, bold: true }, "[R]"),
545073
+ import_react115.default.createElement(
545074
+ Text,
545075
+ { color: theme14.colors.text },
545076
+ " ",
545077
+ t.skillsCreation.regenerate
545078
+ )
544163
545079
  )
544164
545080
  ),
544165
545081
  import_react115.default.createElement(
@@ -544168,7 +545084,7 @@ var init_SkillsCreationPanel = __esm({
544168
545084
  import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544169
545085
  )
544170
545086
  ),
544171
- step === "confirm" && import_react115.default.createElement(
545087
+ mode === "ai" && step === "ai-edit-name" && import_react115.default.createElement(
544172
545088
  Box_default,
544173
545089
  { flexDirection: "column" },
544174
545090
  import_react115.default.createElement(
@@ -544177,63 +545093,26 @@ var init_SkillsCreationPanel = __esm({
544177
545093
  import_react115.default.createElement(
544178
545094
  Text,
544179
545095
  { color: theme14.colors.text },
544180
- t.skillsCreation.nameLabel,
545096
+ t.skillsCreation.editNameLabel,
544181
545097
  " ",
544182
- import_react115.default.createElement(Text, { bold: true, color: theme14.colors.success }, skillName)
545098
+ import_react115.default.createElement(Text, { color: theme14.colors.menuNormal }, skillName)
544183
545099
  )
544184
545100
  ),
544185
545101
  import_react115.default.createElement(
544186
545102
  Box_default,
544187
545103
  { marginBottom: 1 },
544188
- import_react115.default.createElement(
544189
- Text,
544190
- { color: theme14.colors.text },
544191
- t.skillsCreation.descriptionLabel,
544192
- " ",
544193
- import_react115.default.createElement(Text, { color: theme14.colors.menuNormal }, description)
544194
- )
544195
- ),
544196
- import_react115.default.createElement(
544197
- Box_default,
544198
- { marginBottom: 1 },
544199
- import_react115.default.createElement(
544200
- Text,
544201
- { color: theme14.colors.text },
544202
- t.skillsCreation.locationLabel,
544203
- " ",
544204
- import_react115.default.createElement(Text, { bold: true, color: theme14.colors.menuSelected }, location === "global" ? t.skillsCreation.locationGlobal : t.skillsCreation.locationProject)
544205
- )
545104
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.editNameHint)
544206
545105
  ),
544207
- import_react115.default.createElement(
545106
+ import_react115.default.createElement(TextInput, { placeholder: t.skillsCreation.editNamePlaceholder, onSubmit: handleEditNameSubmit }),
545107
+ errorMessage && import_react115.default.createElement(
544208
545108
  Box_default,
544209
545109
  { marginTop: 1 },
544210
- import_react115.default.createElement(Text, { color: theme14.colors.text }, t.skillsCreation.confirmQuestion)
545110
+ import_react115.default.createElement(Text, { color: theme14.colors.error }, errorMessage)
544211
545111
  ),
544212
545112
  import_react115.default.createElement(
544213
545113
  Box_default,
544214
- { marginTop: 1, gap: 2 },
544215
- import_react115.default.createElement(
544216
- Box_default,
544217
- null,
544218
- import_react115.default.createElement(Text, { color: theme14.colors.success, bold: true }, "[Y]"),
544219
- import_react115.default.createElement(
544220
- Text,
544221
- { color: theme14.colors.text },
544222
- " ",
544223
- t.skillsCreation.confirmYes
544224
- )
544225
- ),
544226
- import_react115.default.createElement(
544227
- Box_default,
544228
- null,
544229
- import_react115.default.createElement(Text, { color: theme14.colors.error, bold: true }, "[N]"),
544230
- import_react115.default.createElement(
544231
- Text,
544232
- { color: theme14.colors.text },
544233
- " ",
544234
- t.skillsCreation.confirmNo
544235
- )
544236
- )
545114
+ { marginTop: 1 },
545115
+ import_react115.default.createElement(Text, { dimColor: true }, t.skillsCreation.escCancel)
544237
545116
  )
544238
545117
  )
544239
545118
  );
@@ -548248,7 +549127,10 @@ async function handleConversationWithTools(options3) {
548248
549127
  if (subAgentMessage.message.type === "tool_calls") {
548249
549128
  const toolCalls = subAgentMessage.message.tool_calls;
548250
549129
  if (toolCalls && toolCalls.length > 0) {
548251
- const toolMessages = toolCalls.filter((toolCall) => isToolNeedTwoStepDisplay(toolCall.function.name)).map((toolCall) => {
549130
+ const timeConsumingTools = toolCalls.filter((tc) => isToolNeedTwoStepDisplay(tc.function.name));
549131
+ const quickTools = toolCalls.filter((tc) => !isToolNeedTwoStepDisplay(tc.function.name));
549132
+ const newMessages = [];
549133
+ for (const toolCall of timeConsumingTools) {
548252
549134
  const toolDisplay = formatToolCallMessage(toolCall);
548253
549135
  let toolArgs;
548254
549136
  try {
@@ -548264,7 +549146,6 @@ async function handleConversationWithTools(options3) {
548264
549146
  name: toolCall.function.name,
548265
549147
  arguments: toolArgs
548266
549148
  },
548267
- // Don't include toolDisplay for sub-agent tools to avoid showing parameters
548268
549149
  toolCallId: toolCall.id,
548269
549150
  toolPending: true,
548270
549151
  subAgent: {
@@ -548273,109 +549154,176 @@ async function handleConversationWithTools(options3) {
548273
549154
  isComplete: false
548274
549155
  },
548275
549156
  subAgentInternal: true
548276
- // Mark as internal sub-agent message
548277
549157
  };
548278
- return uiMsg;
548279
- });
549158
+ newMessages.push(uiMsg);
549159
+ }
549160
+ if (quickTools.length > 0) {
549161
+ const toolLines = quickTools.map((tc, index) => {
549162
+ const display = formatToolCallMessage(tc);
549163
+ const isLast = index === quickTools.length - 1;
549164
+ const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
549165
+ const params = display.args.map((arg) => `${arg.key}: ${arg.value}`).join(", ");
549166
+ return `
549167
+ \x1B[2m${prefix} ${display.toolName}${params ? ` (${params})` : ""}\x1B[0m`;
549168
+ });
549169
+ const uiMsg = {
549170
+ role: "subagent",
549171
+ content: `\x1B[38;2;184;122;206m\u2687 ${subAgentMessage.agentName}${toolLines.join("")}\x1B[0m`,
549172
+ streaming: false,
549173
+ subAgent: {
549174
+ agentId: subAgentMessage.agentId,
549175
+ agentName: subAgentMessage.agentName,
549176
+ isComplete: false
549177
+ },
549178
+ subAgentInternal: true,
549179
+ // Store pending tool call IDs for later status update
549180
+ pendingToolIds: quickTools.map((tc) => tc.id)
549181
+ };
549182
+ newMessages.push(uiMsg);
549183
+ }
548280
549184
  const sessionMsg = {
548281
549185
  role: "assistant",
548282
549186
  content: toolCalls.map((tc) => {
548283
549187
  const display = formatToolCallMessage(tc);
548284
- return `\u2687\u26A1 ${display.toolName}`;
549188
+ return isToolNeedTwoStepDisplay(tc.function.name) ? `\u2687\u26A1 ${display.toolName}` : `\u2687 ${display.toolName}`;
548285
549189
  }).join(", "),
548286
549190
  subAgentInternal: true,
548287
549191
  tool_calls: toolCalls
548288
549192
  };
548289
549193
  saveMessage(sessionMsg).catch((err) => console.error("Failed to save sub-agent tool call:", err));
548290
- return [...prev, ...toolMessages];
549194
+ return [...prev, ...newMessages];
548291
549195
  }
548292
549196
  }
548293
549197
  if (subAgentMessage.message.type === "tool_result") {
548294
549198
  const msg = subAgentMessage.message;
548295
549199
  const isError2 = msg.content.startsWith("Error:");
548296
- const statusIcon = isError2 ? "\u2717" : "\u2713";
548297
- const statusText = isError2 ? `
549200
+ const isTimeConsumingTool = isToolNeedTwoStepDisplay(msg.tool_name);
549201
+ const sessionMsg = {
549202
+ role: "tool",
549203
+ tool_call_id: msg.tool_call_id,
549204
+ content: msg.content,
549205
+ subAgentInternal: true
549206
+ };
549207
+ saveMessage(sessionMsg).catch((err) => console.error("Failed to save sub-agent tool result:", err));
549208
+ if (isTimeConsumingTool) {
549209
+ const statusIcon = isError2 ? "\u2717" : "\u2713";
549210
+ const statusText = isError2 ? `
548298
549211
  \u2514\u2500 ${msg.content}` : "";
548299
- let terminalResultData;
548300
- if (msg.tool_name === "terminal-execute" && !isError2) {
548301
- try {
548302
- const resultData = JSON.parse(msg.content);
548303
- if (resultData.stdout !== void 0 || resultData.stderr !== void 0) {
548304
- terminalResultData = {
548305
- stdout: resultData.stdout,
548306
- stderr: resultData.stderr,
548307
- exitCode: resultData.exitCode,
548308
- command: resultData.command
548309
- };
549212
+ let terminalResultData;
549213
+ if (msg.tool_name === "terminal-execute" && !isError2) {
549214
+ try {
549215
+ const resultData = JSON.parse(msg.content);
549216
+ if (resultData.stdout !== void 0 || resultData.stderr !== void 0) {
549217
+ terminalResultData = {
549218
+ stdout: resultData.stdout,
549219
+ stderr: resultData.stderr,
549220
+ exitCode: resultData.exitCode,
549221
+ command: resultData.command
549222
+ };
549223
+ }
549224
+ } catch (e) {
548310
549225
  }
548311
- } catch (e) {
548312
549226
  }
549227
+ let fileToolData = void 0;
549228
+ if (!isError2 && (msg.tool_name === "filesystem-create" || msg.tool_name === "filesystem-edit" || msg.tool_name === "filesystem-edit_search")) {
549229
+ try {
549230
+ const resultData = JSON.parse(msg.content);
549231
+ if (resultData.content) {
549232
+ fileToolData = {
549233
+ name: msg.tool_name,
549234
+ arguments: {
549235
+ content: resultData.content,
549236
+ path: resultData.path || resultData.filename
549237
+ }
549238
+ };
549239
+ } else if (resultData.oldContent && resultData.newContent) {
549240
+ fileToolData = {
549241
+ name: msg.tool_name,
549242
+ arguments: {
549243
+ oldContent: resultData.oldContent,
549244
+ newContent: resultData.newContent,
549245
+ filename: resultData.path || resultData.filename,
549246
+ completeOldContent: resultData.completeOldContent,
549247
+ completeNewContent: resultData.completeNewContent,
549248
+ contextStartLine: resultData.contextStartLine
549249
+ }
549250
+ };
549251
+ } else if (resultData.batchResults && Array.isArray(resultData.batchResults)) {
549252
+ fileToolData = {
549253
+ name: msg.tool_name,
549254
+ arguments: {
549255
+ isBatch: true,
549256
+ batchResults: resultData.batchResults
549257
+ }
549258
+ };
549259
+ }
549260
+ } catch (e) {
549261
+ }
549262
+ }
549263
+ const uiMsg = {
549264
+ role: "subagent",
549265
+ content: `\x1B[38;2;0;186;255m\u2687${statusIcon} ${msg.tool_name}\x1B[0m${statusText}`,
549266
+ streaming: false,
549267
+ toolResult: !isError2 ? msg.content : void 0,
549268
+ terminalResult: terminalResultData,
549269
+ toolCall: terminalResultData ? {
549270
+ name: msg.tool_name,
549271
+ arguments: terminalResultData
549272
+ } : fileToolData ? fileToolData : void 0,
549273
+ subAgent: {
549274
+ agentId: subAgentMessage.agentId,
549275
+ agentName: subAgentMessage.agentName,
549276
+ isComplete: false
549277
+ },
549278
+ subAgentInternal: true
549279
+ };
549280
+ return [...prev, uiMsg];
548313
549281
  }
548314
- let fileToolData = void 0;
548315
- if (!isError2 && (msg.tool_name === "filesystem-create" || msg.tool_name === "filesystem-edit" || msg.tool_name === "filesystem-edit_search")) {
548316
- try {
548317
- const resultData = JSON.parse(msg.content);
548318
- if (resultData.content) {
548319
- fileToolData = {
548320
- name: msg.tool_name,
548321
- arguments: {
548322
- content: resultData.content,
548323
- path: resultData.path || resultData.filename
548324
- }
548325
- };
548326
- } else if (resultData.oldContent && resultData.newContent) {
548327
- fileToolData = {
548328
- name: msg.tool_name,
548329
- arguments: {
548330
- oldContent: resultData.oldContent,
548331
- newContent: resultData.newContent,
548332
- filename: resultData.path || resultData.filename,
548333
- completeOldContent: resultData.completeOldContent,
548334
- completeNewContent: resultData.completeNewContent,
548335
- contextStartLine: resultData.contextStartLine
548336
- }
549282
+ if (isError2) {
549283
+ const statusText = `
549284
+ \u2514\u2500 ${msg.content}`;
549285
+ const uiMsg = {
549286
+ role: "subagent",
549287
+ content: `\x1B[38;2;255;100;100m\u2687\u2717 ${msg.tool_name}\x1B[0m${statusText}`,
549288
+ streaming: false,
549289
+ subAgent: {
549290
+ agentId: subAgentMessage.agentId,
549291
+ agentName: subAgentMessage.agentName,
549292
+ isComplete: false
549293
+ },
549294
+ subAgentInternal: true
549295
+ };
549296
+ return [...prev, uiMsg];
549297
+ }
549298
+ const pendingMsgIndex = prev.findIndex((m) => {
549299
+ var _a22, _b14, _c6;
549300
+ return m.role === "subagent" && ((_a22 = m.subAgent) == null ? void 0 : _a22.agentId) === subAgentMessage.agentId && !((_b14 = m.subAgent) == null ? void 0 : _b14.isComplete) && ((_c6 = m.pendingToolIds) == null ? void 0 : _c6.includes(msg.tool_call_id));
549301
+ });
549302
+ if (pendingMsgIndex !== -1) {
549303
+ const updated = [...prev];
549304
+ const pendingMsg = updated[pendingMsgIndex];
549305
+ if (pendingMsg && pendingMsg.pendingToolIds) {
549306
+ const newPendingIds = pendingMsg.pendingToolIds.filter((id) => id !== msg.tool_call_id);
549307
+ if (newPendingIds.length === 0) {
549308
+ updated[pendingMsgIndex] = {
549309
+ ...pendingMsg,
549310
+ content: `${pendingMsg.content} \x1B[38;2;100;200;100m\u2713\x1B[0m`,
549311
+ pendingToolIds: newPendingIds
548337
549312
  };
548338
- } else if (resultData.batchResults && Array.isArray(resultData.batchResults)) {
548339
- fileToolData = {
548340
- name: msg.tool_name,
548341
- arguments: {
548342
- isBatch: true,
548343
- batchResults: resultData.batchResults
548344
- }
549313
+ } else {
549314
+ updated[pendingMsgIndex] = {
549315
+ ...pendingMsg,
549316
+ pendingToolIds: newPendingIds
548345
549317
  };
548346
549318
  }
548347
- } catch (e) {
548348
549319
  }
549320
+ return updated;
548349
549321
  }
548350
- const uiMsg = {
548351
- role: "subagent",
548352
- content: `\x1B[38;2;0;186;255m\u2687${statusIcon} ${msg.tool_name}\x1B[0m${statusText}`,
548353
- streaming: false,
548354
- toolResult: !isError2 ? msg.content : void 0,
548355
- terminalResult: terminalResultData,
548356
- toolCall: terminalResultData ? {
548357
- name: msg.tool_name,
548358
- arguments: terminalResultData
548359
- } : fileToolData ? fileToolData : void 0,
548360
- subAgent: {
548361
- agentId: subAgentMessage.agentId,
548362
- agentName: subAgentMessage.agentName,
548363
- isComplete: false
548364
- },
548365
- subAgentInternal: true
548366
- };
548367
- const sessionMsg = {
548368
- role: "tool",
548369
- tool_call_id: msg.tool_call_id,
548370
- content: msg.content,
548371
- subAgentInternal: true
548372
- };
548373
- saveMessage(sessionMsg).catch((err) => console.error("Failed to save sub-agent tool result:", err));
548374
- return [...prev, uiMsg];
549322
+ return prev;
548375
549323
  }
548376
549324
  const existingIndex = prev.findIndex((m) => {
548377
549325
  var _a22, _b14;
548378
- return m.role === "subagent" && ((_a22 = m.subAgent) == null ? void 0 : _a22.agentId) === subAgentMessage.agentId && !((_b14 = m.subAgent) == null ? void 0 : _b14.isComplete) && !m.toolCall;
549326
+ return m.role === "subagent" && ((_a22 = m.subAgent) == null ? void 0 : _a22.agentId) === subAgentMessage.agentId && !((_b14 = m.subAgent) == null ? void 0 : _b14.isComplete) && !m.pendingToolIds;
548379
549327
  });
548380
549328
  let content = "";
548381
549329
  if (subAgentMessage.message.type === "content") {
@@ -548867,43 +549815,64 @@ function convertSessionMessagesToUI(sessionMessages) {
548867
549815
  const msg = sessionMessages[i];
548868
549816
  if (!msg)
548869
549817
  continue;
548870
- if (msg.role === "system")
548871
- continue;
548872
549818
  if (msg.subAgentInternal && msg.role === "assistant" && msg.tool_calls) {
548873
- for (const toolCall of msg.tool_calls) {
548874
- if (isToolNeedTwoStepDisplay(toolCall.function.name)) {
548875
- const toolDisplay = formatToolCallMessage(toolCall);
548876
- let toolArgs;
548877
- try {
548878
- toolArgs = JSON.parse(toolCall.function.arguments);
548879
- } catch (e) {
548880
- toolArgs = {};
548881
- }
548882
- uiMessages.push({
548883
- role: "subagent",
548884
- content: `\x1B[38;2;184;122;206m\u2687\u26A1 ${toolDisplay.toolName}\x1B[0m`,
548885
- streaming: false,
548886
- toolCall: {
548887
- name: toolCall.function.name,
548888
- arguments: toolArgs
548889
- },
548890
- // Don't include toolDisplay for sub-agent tools to avoid showing parameters
548891
- toolCallId: toolCall.id,
548892
- toolPending: false,
548893
- subAgentInternal: true
548894
- });
549819
+ const timeConsumingTools = msg.tool_calls.filter((tc) => isToolNeedTwoStepDisplay(tc.function.name));
549820
+ const quickTools = msg.tool_calls.filter((tc) => !isToolNeedTwoStepDisplay(tc.function.name));
549821
+ for (const toolCall of timeConsumingTools) {
549822
+ const toolDisplay = formatToolCallMessage(toolCall);
549823
+ let toolArgs;
549824
+ try {
549825
+ toolArgs = JSON.parse(toolCall.function.arguments);
549826
+ } catch (e) {
549827
+ toolArgs = {};
548895
549828
  }
549829
+ uiMessages.push({
549830
+ role: "subagent",
549831
+ content: `\x1B[38;2;184;122;206m\u2687\u26A1 ${toolDisplay.toolName}\x1B[0m`,
549832
+ streaming: false,
549833
+ toolCall: {
549834
+ name: toolCall.function.name,
549835
+ arguments: toolArgs
549836
+ },
549837
+ toolCallId: toolCall.id,
549838
+ toolPending: false,
549839
+ subAgentInternal: true
549840
+ });
548896
549841
  processedToolCalls.add(toolCall.id);
548897
549842
  }
549843
+ if (quickTools.length > 0) {
549844
+ let agentName = "Sub-Agent";
549845
+ for (let j = i + 1; j < sessionMessages.length; j++) {
549846
+ const nextMsg = sessionMessages[j];
549847
+ if (nextMsg && nextMsg.subAgentInternal && nextMsg.role === "tool") {
549848
+ break;
549849
+ }
549850
+ }
549851
+ const toolLines = quickTools.map((tc, index) => {
549852
+ const display = formatToolCallMessage(tc);
549853
+ const isLast = index === quickTools.length - 1;
549854
+ const prefix = isLast ? "\u2514\u2500" : "\u251C\u2500";
549855
+ const params = display.args.map((arg) => `${arg.key}: ${arg.value}`).join(", ");
549856
+ return `
549857
+ \x1B[2m${prefix} ${display.toolName}${params ? ` (${params})` : ""}\x1B[0m`;
549858
+ });
549859
+ uiMessages.push({
549860
+ role: "subagent",
549861
+ content: `\x1B[38;2;184;122;206m\u2687 ${agentName}${toolLines.join("")}\x1B[0m`,
549862
+ streaming: false,
549863
+ subAgentInternal: true,
549864
+ pendingToolIds: quickTools.map((tc) => tc.id)
549865
+ });
549866
+ for (const tc of quickTools) {
549867
+ processedToolCalls.add(tc.id);
549868
+ }
549869
+ }
548898
549870
  continue;
548899
549871
  }
548900
549872
  if (msg.subAgentInternal && msg.role === "tool" && msg.tool_call_id) {
548901
549873
  const isError2 = msg.content.startsWith("Error:");
548902
- const statusIcon = isError2 ? "\u2717" : "\u2713";
548903
- const statusText = isError2 ? `
548904
- \u2514\u2500 ${msg.content}` : "";
548905
549874
  let toolName = "tool";
548906
- let terminalResultData;
549875
+ let isTimeConsumingTool = false;
548907
549876
  for (let j = i - 1; j >= 0; j--) {
548908
549877
  const prevMsg = sessionMessages[j];
548909
549878
  if (!prevMsg)
@@ -548912,36 +549881,90 @@ function convertSessionMessagesToUI(sessionMessages) {
548912
549881
  const tc = prevMsg.tool_calls.find((t) => t.id === msg.tool_call_id);
548913
549882
  if (tc) {
548914
549883
  toolName = tc.function.name;
548915
- if (toolName === "terminal-execute" && !isError2) {
548916
- try {
548917
- const resultData = JSON.parse(msg.content);
548918
- if (resultData.stdout !== void 0 || resultData.stderr !== void 0) {
548919
- terminalResultData = {
548920
- stdout: resultData.stdout,
548921
- stderr: resultData.stderr,
548922
- exitCode: resultData.exitCode,
548923
- command: resultData.command
548924
- };
549884
+ isTimeConsumingTool = isToolNeedTwoStepDisplay(toolName);
549885
+ break;
549886
+ }
549887
+ }
549888
+ }
549889
+ if (isTimeConsumingTool) {
549890
+ const statusIcon = isError2 ? "\u2717" : "\u2713";
549891
+ const statusText = isError2 ? `
549892
+ \u2514\u2500 ${msg.content}` : "";
549893
+ let terminalResultData;
549894
+ if (toolName === "terminal-execute" && !isError2) {
549895
+ try {
549896
+ const resultData = JSON.parse(msg.content);
549897
+ if (resultData.stdout !== void 0 || resultData.stderr !== void 0) {
549898
+ terminalResultData = {
549899
+ stdout: resultData.stdout,
549900
+ stderr: resultData.stderr,
549901
+ exitCode: resultData.exitCode,
549902
+ command: resultData.command
549903
+ };
549904
+ }
549905
+ } catch (e) {
549906
+ }
549907
+ }
549908
+ let fileToolData = void 0;
549909
+ if (!isError2 && (toolName === "filesystem-create" || toolName === "filesystem-edit" || toolName === "filesystem-edit_search")) {
549910
+ try {
549911
+ const resultData = JSON.parse(msg.content);
549912
+ if (resultData.content) {
549913
+ fileToolData = {
549914
+ name: toolName,
549915
+ arguments: {
549916
+ content: resultData.content,
549917
+ path: resultData.path || resultData.filename
548925
549918
  }
548926
- } catch (e) {
548927
- }
549919
+ };
549920
+ } else if (resultData.oldContent && resultData.newContent) {
549921
+ fileToolData = {
549922
+ name: toolName,
549923
+ arguments: {
549924
+ oldContent: resultData.oldContent,
549925
+ newContent: resultData.newContent,
549926
+ filename: resultData.path || resultData.filename,
549927
+ completeOldContent: resultData.completeOldContent,
549928
+ completeNewContent: resultData.completeNewContent,
549929
+ contextStartLine: resultData.contextStartLine
549930
+ }
549931
+ };
549932
+ } else if (resultData.batchResults && Array.isArray(resultData.batchResults)) {
549933
+ fileToolData = {
549934
+ name: toolName,
549935
+ arguments: {
549936
+ isBatch: true,
549937
+ batchResults: resultData.batchResults
549938
+ }
549939
+ };
548928
549940
  }
548929
- break;
549941
+ } catch (e) {
548930
549942
  }
548931
549943
  }
549944
+ uiMessages.push({
549945
+ role: "subagent",
549946
+ content: `\x1B[38;2;0;186;255m\u2687${statusIcon} ${toolName}\x1B[0m${statusText}`,
549947
+ streaming: false,
549948
+ toolResult: !isError2 ? msg.content : void 0,
549949
+ terminalResult: terminalResultData,
549950
+ toolCall: terminalResultData ? {
549951
+ name: toolName,
549952
+ arguments: terminalResultData
549953
+ } : fileToolData ? fileToolData : void 0,
549954
+ subAgentInternal: true
549955
+ });
549956
+ } else {
549957
+ if (isError2) {
549958
+ const statusText = `
549959
+ \u2514\u2500 ${msg.content}`;
549960
+ uiMessages.push({
549961
+ role: "subagent",
549962
+ content: `\x1B[38;2;255;100;100m\u2687\u2717 ${toolName}\x1B[0m${statusText}`,
549963
+ streaming: false,
549964
+ subAgentInternal: true
549965
+ });
549966
+ }
548932
549967
  }
548933
- uiMessages.push({
548934
- role: "subagent",
548935
- content: `\x1B[38;2;0;186;255m\u2687${statusIcon} ${toolName}\x1B[0m${statusText}`,
548936
- streaming: false,
548937
- toolResult: !isError2 ? msg.content : void 0,
548938
- terminalResult: terminalResultData,
548939
- toolCall: terminalResultData ? {
548940
- name: toolName,
548941
- arguments: terminalResultData
548942
- } : void 0,
548943
- subAgentInternal: true
548944
- });
548945
549968
  continue;
548946
549969
  }
548947
549970
  if (msg.role === "assistant" && msg.tool_calls && msg.tool_calls.length > 0 && !msg.subAgentInternal) {
@@ -551371,9 +552394,9 @@ var init_handler = __esm({
551371
552394
  if (this.fsw.closed) {
551372
552395
  return;
551373
552396
  }
551374
- const dirname10 = sysPath.dirname(file);
552397
+ const dirname11 = sysPath.dirname(file);
551375
552398
  const basename6 = sysPath.basename(file);
551376
- const parent = this.fsw._getWatchedDir(dirname10);
552399
+ const parent = this.fsw._getWatchedDir(dirname11);
551377
552400
  let prevStats = stats;
551378
552401
  if (parent.has(basename6))
551379
552402
  return;
@@ -551400,7 +552423,7 @@ var init_handler = __esm({
551400
552423
  prevStats = newStats2;
551401
552424
  }
551402
552425
  } catch (error) {
551403
- this.fsw._remove(dirname10, basename6);
552426
+ this.fsw._remove(dirname11, basename6);
551404
552427
  }
551405
552428
  } else if (parent.has(basename6)) {
551406
552429
  const at = newStats.atimeMs;
@@ -551645,11 +552668,11 @@ function createPattern(matcher2) {
551645
552668
  if (matcher2.path === string)
551646
552669
  return true;
551647
552670
  if (matcher2.recursive) {
551648
- const relative8 = sysPath2.relative(matcher2.path, string);
551649
- if (!relative8) {
552671
+ const relative9 = sysPath2.relative(matcher2.path, string);
552672
+ if (!relative9) {
551650
552673
  return false;
551651
552674
  }
551652
- return !relative8.startsWith("..") && !sysPath2.isAbsolute(relative8);
552675
+ return !relative9.startsWith("..") && !sysPath2.isAbsolute(relative9);
551653
552676
  }
551654
552677
  return false;
551655
552678
  };
@@ -554067,43 +555090,34 @@ function ChatScreen({ autoResume, enableYolo }) {
554067
555090
  await saveCustomCommand(name, command, type, void 0, location, workingDirectory);
554068
555091
  await registerCustomCommands(workingDirectory);
554069
555092
  panelState.setShowCustomCommandConfig(false);
554070
- const typeDesc = type === "execute" ? "Execute in terminal" : "Send to AI";
554071
- const locationDesc = location === "global" ? "Global (~/.snow/commands/)" : "Project (.snow/commands/)";
555093
+ const typeDesc = type === "execute" ? t.customCommand.resultTypeExecute : t.customCommand.resultTypePrompt;
555094
+ const locationDesc = location === "global" ? t.customCommand.resultLocationGlobal : t.customCommand.resultLocationProject;
555095
+ const content = t.customCommand.saveSuccessMessage.replace("{name}", name).replace("{type}", typeDesc).replace("{location}", locationDesc);
554072
555096
  const successMessage = {
554073
555097
  role: "command",
554074
- content: `Custom command '${name}' saved successfully!
554075
- Type: ${typeDesc}
554076
- Location: ${locationDesc}
554077
- You can now use /${name}`,
555098
+ content,
554078
555099
  commandName: "custom"
554079
555100
  };
554080
555101
  setMessages((prev) => [...prev, successMessage]);
554081
- }, onSkillsSave: async (skillName, description, location) => {
554082
- const result2 = await createSkillTemplate(skillName, description, location, workingDirectory);
555102
+ }, onSkillsSave: async (skillName, description, location, generated) => {
555103
+ const result2 = generated ? await createSkillFromGenerated(skillName, description, generated, location, workingDirectory) : await createSkillTemplate(skillName, description, location, workingDirectory);
554083
555104
  panelState.setShowSkillsCreation(false);
554084
555105
  if (result2.success) {
554085
- const locationDesc = location === "global" ? "Global (~/.snow/skills/)" : "Project (.snow/skills/)";
555106
+ const locationDesc = location === "global" ? t.skillsCreation.locationGlobal : t.skillsCreation.locationProject;
555107
+ const modeDesc = generated ? t.skillsCreation.resultModeAi : t.skillsCreation.resultModeManual;
555108
+ const content = t.skillsCreation.createSuccessMessage.replace("{name}", skillName).replace("{mode}", modeDesc).replace("{location}", locationDesc).replace("{path}", result2.path);
554086
555109
  const successMessage = {
554087
555110
  role: "command",
554088
- content: `Skill '${skillName}' created successfully!
554089
- Location: ${locationDesc}
554090
- Path: ${result2.path}
554091
-
554092
- The following files have been created:
554093
- - SKILL.md (main skill documentation)
554094
- - reference.md (detailed reference)
554095
- - examples.md (usage examples)
554096
- - templates/template.txt (template file)
554097
- - scripts/helper.py (helper script)
554098
-
554099
- You can now edit these files to customize your skill.`,
555111
+ content,
554100
555112
  commandName: "skills"
554101
555113
  };
554102
555114
  setMessages((prev) => [...prev, successMessage]);
554103
555115
  } else {
555116
+ const errorText = result2.error || t.skillsCreation.errorUnknown;
555117
+ const content = t.skillsCreation.createErrorMessage.replace("{error}", errorText);
554104
555118
  const errorMessage = {
554105
555119
  role: "command",
554106
- content: `Failed to create skill: ${result2.error}`,
555120
+ content,
554107
555121
  commandName: "skills"
554108
555122
  };
554109
555123
  setMessages((prev) => [...prev, errorMessage]);