snow-flow 10.0.65 → 10.0.66

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json.schemastore.org/package.json",
3
- "version": "10.0.65",
3
+ "version": "10.0.66",
4
4
  "name": "snow-flow",
5
5
  "description": "Snow-Flow - ServiceNow Multi-Agent Development Framework powered by AI",
6
6
  "license": "Elastic-2.0",
@@ -346,7 +346,7 @@ export function Autocomplete(props: {
346
346
 
347
347
  for (const serverCommand of sync.data.command) {
348
348
  results.push({
349
- display: "/" + serverCommand.name + (serverCommand.mcp ? " (MCP)" : ""),
349
+ display: "/" + serverCommand.name + (serverCommand.source === "mcp" ? " (MCP)" : serverCommand.source === "skill" ? " (Skill)" : ""),
350
350
  description: serverCommand.description,
351
351
  onSelect: () => {
352
352
  const newText = "/" + serverCommand.name + " "
@@ -6,6 +6,7 @@ import { Identifier } from "../id/id"
6
6
  import PROMPT_INITIALIZE from "./template/initialize.txt"
7
7
  import PROMPT_REVIEW from "./template/review.txt"
8
8
  import { MCP } from "../mcp"
9
+ import { Skill } from "../skill"
9
10
 
10
11
  export namespace Command {
11
12
  export const Event = {
@@ -26,7 +27,7 @@ export namespace Command {
26
27
  description: z.string().optional(),
27
28
  agent: z.string().optional(),
28
29
  model: z.string().optional(),
29
- mcp: z.boolean().optional(),
30
+ source: z.enum(["command", "mcp", "skill"]).optional(),
30
31
  // workaround for zod not supporting async functions natively so we use getters
31
32
  // https://zod.dev/v4/changelog?id=zfunction
32
33
  template: z.promise(z.string()).or(z.string()),
@@ -62,6 +63,7 @@ export namespace Command {
62
63
  [Default.INIT]: {
63
64
  name: Default.INIT,
64
65
  description: "create/update AGENTS.md",
66
+ source: "command",
65
67
  get template() {
66
68
  return PROMPT_INITIALIZE.replace("${path}", Instance.worktree)
67
69
  },
@@ -70,6 +72,7 @@ export namespace Command {
70
72
  [Default.REVIEW]: {
71
73
  name: Default.REVIEW,
72
74
  description: "review changes [commit|branch|pr], defaults to uncommitted",
75
+ source: "command",
73
76
  get template() {
74
77
  return PROMPT_REVIEW.replace("${path}", Instance.worktree)
75
78
  },
@@ -84,6 +87,7 @@ export namespace Command {
84
87
  agent: command.agent,
85
88
  model: command.model,
86
89
  description: command.description,
90
+ source: "command",
87
91
  get template() {
88
92
  return command.template
89
93
  },
@@ -94,7 +98,7 @@ export namespace Command {
94
98
  for (const [name, prompt] of Object.entries(await MCP.prompts())) {
95
99
  result[name] = {
96
100
  name,
97
- mcp: true,
101
+ source: "mcp",
98
102
  description: prompt.description,
99
103
  get template() {
100
104
  // since a getter can't be async we need to manually return a promise here
@@ -118,6 +122,20 @@ export namespace Command {
118
122
  }
119
123
  }
120
124
 
125
+ // Add skills as invocable commands
126
+ for (const skill of await Skill.all()) {
127
+ if (result[skill.name]) continue
128
+ result[skill.name] = {
129
+ name: skill.name,
130
+ description: skill.description,
131
+ source: "skill",
132
+ get template() {
133
+ return skill.content
134
+ },
135
+ hints: [],
136
+ }
137
+ }
138
+
121
139
  return result
122
140
  })
123
141
 
@@ -17,6 +17,7 @@ export namespace Skill {
17
17
  name: z.string(),
18
18
  description: z.string(),
19
19
  location: z.string(),
20
+ content: z.string(),
20
21
  })
21
22
  export type Info = z.infer<typeof Info>
22
23
 
@@ -73,6 +74,7 @@ export namespace Skill {
73
74
  name: parsed.data.name,
74
75
  description: parsed.data.description,
75
76
  location: match,
77
+ content: md.content,
76
78
  }
77
79
  }
78
80
 
package/src/tool/skill.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import path from "path"
2
+ import { pathToFileURL } from "url"
2
3
  import z from "zod"
3
4
  import { Tool } from "./tool"
4
5
  import { Skill } from "../skill"
5
- import { ConfigMarkdown } from "../config/markdown"
6
6
  import { PermissionNext } from "../permission/next"
7
7
 
8
8
  export const SkillTool = Tool.define("skill", async (ctx) => {
@@ -30,10 +30,11 @@ export const SkillTool = Tool.define("skill", async (ctx) => {
30
30
  ` <skill>`,
31
31
  ` <name>${skill.name}</name>`,
32
32
  ` <description>${skill.description}</description>`,
33
+ ` <location>${pathToFileURL(skill.location).href}</location>`,
33
34
  ` </skill>`,
34
35
  ]),
35
36
  "</available_skills>",
36
- ].join(" ")
37
+ ].join("\n")
37
38
 
38
39
  const examples = accessibleSkills
39
40
  .map((skill) => `'${skill.name}'`)
@@ -62,12 +63,16 @@ export const SkillTool = Tool.define("skill", async (ctx) => {
62
63
  always: [params.name],
63
64
  metadata: {},
64
65
  })
65
- // Load and parse skill content
66
- const parsed = await ConfigMarkdown.parse(skill.location)
66
+
67
67
  const dir = path.dirname(skill.location)
68
68
 
69
- // Format output similar to plugin pattern
70
- const output = [`## Skill: ${skill.name}`, "", `**Base directory**: ${dir}`, "", parsed.content.trim()].join("\n")
69
+ const output = [
70
+ `<skill_content name="${skill.name}">`,
71
+ `<location>${pathToFileURL(skill.location).href}</location>`,
72
+ `<base_directory>${dir}</base_directory>`,
73
+ skill.content.trim(),
74
+ `</skill_content>`,
75
+ ].join("\n")
71
76
 
72
77
  return {
73
78
  title: `Loaded skill: ${skill.name}`,