dsh-comfyui 0.3.0-beta.5 → 0.4.0
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/README.en.md +65 -168
- package/README.md +63 -166
- package/client/client.js +831 -33
- package/client/client.js.map +1 -1
- package/lib/config.d.ts +14 -0
- package/lib/config.js +6 -0
- package/lib/index.js +30 -10
- package/lib/routes.js +259 -0
- package/lib/skill.js +50 -3
- package/lib/skillpack.d.ts +262 -0
- package/lib/skillpack.js +774 -0
- package/lib/store.d.ts +13 -0
- package/lib/store.js +36 -0
- package/lib/tools.d.ts +3 -0
- package/lib/tools.js +289 -3
- package/package.json +4 -9
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sub-directories offered by default. These are suggestions, not a whitelist:
|
|
3
|
+
* a pack may hold any directory whose name matches {@link DIR_NAME}, so a user
|
|
4
|
+
* can follow whatever layout their other tooling expects. The list covers the
|
|
5
|
+
* conventions this plugin's packs are most likely to meet — the host skill
|
|
6
|
+
* bundle shape (`references` / `scripts` / `assets`) plus the names agent and
|
|
7
|
+
* prompt tooling commonly use.
|
|
8
|
+
*/
|
|
9
|
+
export declare const SKILL_PRESET_DIRS: readonly ["references", "scripts", "assets", "templates", "agents", "examples", "prompts", "commands", "docs", "data"];
|
|
10
|
+
/** A pack sub-directory name. Any {@link DIR_NAME}-valid name is accepted. */
|
|
11
|
+
export type SkillBucket = string;
|
|
12
|
+
/** The main document; it is the body `action: skill` returns and cannot be renamed or deleted. */
|
|
13
|
+
export declare const SKILL_MAIN = "SKILL.md";
|
|
14
|
+
/** One text file may not exceed this: SKILL.md is injected into the model context whole. */
|
|
15
|
+
export declare const MAX_FILE_BYTES: number;
|
|
16
|
+
/** Imported binaries live in `assets/` and never enter the prompt as text, so
|
|
17
|
+
* they get a larger budget than the documents the model reads verbatim. */
|
|
18
|
+
export declare const MAX_ASSET_BYTES: number;
|
|
19
|
+
/** A pack is documentation, not storage — these caps keep it that way. */
|
|
20
|
+
export declare const MAX_PACK_FILES = 100;
|
|
21
|
+
export declare const MAX_PACK_BYTES: number;
|
|
22
|
+
/** One file inside a pack. */
|
|
23
|
+
export interface SkillFileInfo {
|
|
24
|
+
/** Path relative to the pack root, always forward-slashed (`references/styles.md`). */
|
|
25
|
+
path: string;
|
|
26
|
+
size: number;
|
|
27
|
+
updatedAt: string;
|
|
28
|
+
}
|
|
29
|
+
/** A pack's listing plus the catalog summary derived from SKILL.md. */
|
|
30
|
+
export interface SkillPackInfo {
|
|
31
|
+
slug: string;
|
|
32
|
+
/** Absolute directory path; handed to the model as the skill's resource base. */
|
|
33
|
+
dir: string;
|
|
34
|
+
/** Short routing line shown by `comfyui_workflow action: list`. */
|
|
35
|
+
summary: string;
|
|
36
|
+
files: SkillFileInfo[];
|
|
37
|
+
/** Sub-directories present in the pack, including empty ones. */
|
|
38
|
+
dirs: string[];
|
|
39
|
+
totalBytes: number;
|
|
40
|
+
}
|
|
41
|
+
/** A successful operation, or a message the panel and tools show verbatim. */
|
|
42
|
+
export type SkillPackResult<T> = {
|
|
43
|
+
ok: true;
|
|
44
|
+
value: T;
|
|
45
|
+
} | {
|
|
46
|
+
ok: false;
|
|
47
|
+
error: string;
|
|
48
|
+
};
|
|
49
|
+
/** The MIME type used when serving one pack file. */
|
|
50
|
+
export declare function contentTypeOf(path: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Where an imported file belongs when the user did not pick a bucket.
|
|
53
|
+
*
|
|
54
|
+
* Host-side on purpose: the panel sends a file name and gets the resolved path
|
|
55
|
+
* back, so the extension→bucket rule has exactly one definition.
|
|
56
|
+
* @param file - the imported file's base name.
|
|
57
|
+
* @returns the bucket to place it in, or undefined when the type is not accepted.
|
|
58
|
+
*/
|
|
59
|
+
export declare function defaultBucketFor(file: string): Exclude<SkillBucket, ''> | undefined;
|
|
60
|
+
/**
|
|
61
|
+
* Build a stable directory name for a workflow's pack.
|
|
62
|
+
*
|
|
63
|
+
* The readable half is for whoever opens the folder in an editor; the id suffix
|
|
64
|
+
* makes it unique and, more importantly, keeps the directory put when the user
|
|
65
|
+
* renames the workflow — a pack that moved on every rename would strand the
|
|
66
|
+
* absolute path already handed to a running agent.
|
|
67
|
+
* @param name - the workflow's display name.
|
|
68
|
+
* @param id - the workflow id.
|
|
69
|
+
* @returns a slug matching the {@link SLUG} grammar.
|
|
70
|
+
*/
|
|
71
|
+
export declare function skillSlug(name: string, id: string): string;
|
|
72
|
+
/**
|
|
73
|
+
* Split and validate a pack-relative path.
|
|
74
|
+
* @param path - candidate relative path such as `references/styles.md`.
|
|
75
|
+
* @returns the bucket and file name, or an error message.
|
|
76
|
+
*/
|
|
77
|
+
export declare function parseSkillPath(path: string): SkillPackResult<{
|
|
78
|
+
bucket: SkillBucket;
|
|
79
|
+
file: string;
|
|
80
|
+
}>;
|
|
81
|
+
/**
|
|
82
|
+
* Validate one sub-directory name from the browser or a tool call.
|
|
83
|
+
* @param name - candidate directory name.
|
|
84
|
+
* @returns the name, or why it was refused.
|
|
85
|
+
*/
|
|
86
|
+
export declare function parseSkillDir(name: string): SkillPackResult<string>;
|
|
87
|
+
/**
|
|
88
|
+
* Strip a leading `---` frontmatter block and read its `summary` key.
|
|
89
|
+
*
|
|
90
|
+
* Deliberately not a YAML parser: the only key this plugin interprets is
|
|
91
|
+
* `summary`, and a dependency for one line of text is not worth it. Unknown
|
|
92
|
+
* keys survive untouched in the file for whoever edits it by hand.
|
|
93
|
+
* @param text - the raw SKILL.md contents.
|
|
94
|
+
* @returns the body without frontmatter plus the summary when present.
|
|
95
|
+
*/
|
|
96
|
+
export declare function splitFrontmatter(text: string): {
|
|
97
|
+
body: string;
|
|
98
|
+
summary: string;
|
|
99
|
+
};
|
|
100
|
+
/** Compose SKILL.md text from a summary and a body, keeping the frontmatter canonical. */
|
|
101
|
+
export declare function joinFrontmatter(summary: string, body: string): string;
|
|
102
|
+
/**
|
|
103
|
+
* The skill-pack directory tree under the plugin data directory.
|
|
104
|
+
*
|
|
105
|
+
* One instance per plugin fiber; every method takes the pack slug so a single
|
|
106
|
+
* store serves the whole library.
|
|
107
|
+
*/
|
|
108
|
+
export declare class SkillPackStore {
|
|
109
|
+
private readonly resolveRoot;
|
|
110
|
+
/**
|
|
111
|
+
* @param root - the pack directory tree, or a getter when it follows a config
|
|
112
|
+
* value the settings page can change while the plugin runs.
|
|
113
|
+
*/
|
|
114
|
+
constructor(root: string | (() => string));
|
|
115
|
+
/** The current pack root (re-read per call: `skillsDir` is hot-configurable). */
|
|
116
|
+
get root(): string;
|
|
117
|
+
/** Absolute path of one pack, after re-validating the slug from workflows.json. */
|
|
118
|
+
private dirOf;
|
|
119
|
+
/** Absolute path of one file inside a pack, guarded twice: grammar, then containment. */
|
|
120
|
+
private fileOf;
|
|
121
|
+
/** Create the pack directory and seed SKILL.md when it does not exist yet. */
|
|
122
|
+
create(slug: string, seed: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
123
|
+
/**
|
|
124
|
+
* Find a pack directory belonging to a workflow id, whatever its readable
|
|
125
|
+
* half says. Detaching a pack keeps the directory, and the workflow may have
|
|
126
|
+
* been renamed since: without this, re-enabling would mint a new slug and
|
|
127
|
+
* strand the user's hand-written notes in the old directory.
|
|
128
|
+
* @param id - the workflow id whose suffix the directory carries.
|
|
129
|
+
* @returns the matching slug, or undefined.
|
|
130
|
+
*/
|
|
131
|
+
findBySuffix(id: string): Promise<string | undefined>;
|
|
132
|
+
/** Whether the pack directory exists on disk. */
|
|
133
|
+
exists(slug: string): Promise<boolean>;
|
|
134
|
+
/** List a pack: SKILL.md plus one level of each bucket, with its derived summary. */
|
|
135
|
+
info(slug: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
136
|
+
/** Create one sub-directory. Empty directories are legal — a user may lay a
|
|
137
|
+
* pack out before filling it in. */
|
|
138
|
+
makeDir(slug: string, name: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
139
|
+
/** Read one file as text. */
|
|
140
|
+
read(slug: string, path: string): Promise<SkillPackResult<string>>;
|
|
141
|
+
/** SKILL.md body with frontmatter stripped — the text handed to the model. */
|
|
142
|
+
body(slug: string): Promise<SkillPackResult<{
|
|
143
|
+
body: string;
|
|
144
|
+
summary: string;
|
|
145
|
+
dir: string;
|
|
146
|
+
}>>;
|
|
147
|
+
/** Create or overwrite one text file. */
|
|
148
|
+
write(slug: string, path: string, content: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
149
|
+
/**
|
|
150
|
+
* Create or overwrite one file from raw bytes, enforcing the per-file and
|
|
151
|
+
* per-pack caps. The text and import paths share this so an imported file
|
|
152
|
+
* can never bypass a limit the editor honours.
|
|
153
|
+
*/
|
|
154
|
+
writeBytes(slug: string, path: string, bytes: Buffer): Promise<SkillPackResult<SkillPackInfo>>;
|
|
155
|
+
/** Read one file as raw bytes (the panel's image preview and downloads). */
|
|
156
|
+
readBytes(slug: string, path: string): Promise<SkillPackResult<Buffer>>;
|
|
157
|
+
/** Rename one file; SKILL.md is fixed and both sides are validated. */
|
|
158
|
+
rename(slug: string, from: string, to: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
159
|
+
/** Delete one file; SKILL.md is fixed. */
|
|
160
|
+
remove(slug: string, path: string): Promise<SkillPackResult<SkillPackInfo>>;
|
|
161
|
+
/** Delete the whole pack directory. Only the explicit destroy gesture calls this. */
|
|
162
|
+
destroy(slug: string): Promise<SkillPackResult<true>>;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* The SKILL.md a freshly enabled pack starts from.
|
|
166
|
+
*
|
|
167
|
+
* The seed is a table of contents on purpose: the body is what every
|
|
168
|
+
* `action: skill` call pays for, so it should point at reference files rather
|
|
169
|
+
* than hold their content.
|
|
170
|
+
* @param workflowName - the workflow this pack documents.
|
|
171
|
+
* @param parameters - adjustable parameter names, listed as a starting point.
|
|
172
|
+
* @returns SKILL.md text including frontmatter.
|
|
173
|
+
*/
|
|
174
|
+
export declare function seedSkillDocument(workflowName: string, parameters: string[]): string;
|
|
175
|
+
/** A pack as the panel and the tools see it: the listing plus its workflow-side flags. */
|
|
176
|
+
export interface WorkflowSkillPack extends SkillPackInfo {
|
|
177
|
+
workflowId: string;
|
|
178
|
+
workflowName: string;
|
|
179
|
+
/** Whether `action: run` refuses until the agent has read this pack. */
|
|
180
|
+
required: boolean;
|
|
181
|
+
}
|
|
182
|
+
/** The pack body handed to the model by `comfyui_workflow action: skill`. */
|
|
183
|
+
export interface WorkflowSkillBody {
|
|
184
|
+
workflowId: string;
|
|
185
|
+
workflowName: string;
|
|
186
|
+
summary: string;
|
|
187
|
+
body: string;
|
|
188
|
+
/** Absolute directory the model resolves relative paths against. */
|
|
189
|
+
resourceBase: string;
|
|
190
|
+
/** Everything in the pack, so the model does not have to list the directory. */
|
|
191
|
+
files: string[];
|
|
192
|
+
}
|
|
193
|
+
/** Minimal slice of the workflow store the pack API needs. */
|
|
194
|
+
interface SkillPackHost {
|
|
195
|
+
/** Pack root; a getter when it follows a config value that can change. */
|
|
196
|
+
readonly skillsRoot: string | (() => string);
|
|
197
|
+
getWorkflow(id: string): Promise<StoredWorkflowLike | undefined>;
|
|
198
|
+
updateWorkflowSkill(id: string, patch: {
|
|
199
|
+
skillDir?: string | null;
|
|
200
|
+
requireSkill?: boolean;
|
|
201
|
+
}): Promise<StoredWorkflowLike | undefined>;
|
|
202
|
+
}
|
|
203
|
+
/** Structural view of a stored workflow (avoids importing the store class). */
|
|
204
|
+
interface StoredWorkflowLike {
|
|
205
|
+
id: string;
|
|
206
|
+
name: string;
|
|
207
|
+
skillDir?: string;
|
|
208
|
+
requireSkill?: boolean;
|
|
209
|
+
parameters?: Array<{
|
|
210
|
+
name: string;
|
|
211
|
+
}>;
|
|
212
|
+
}
|
|
213
|
+
/** Workflow-aware skill-pack operations shared by the tools and the panel routes. */
|
|
214
|
+
export interface WorkflowSkillPacks {
|
|
215
|
+
/** Absolute root of all packs (shown in the panel so users can open it). */
|
|
216
|
+
readonly root: string;
|
|
217
|
+
/** One workflow's pack, or undefined when it has none. */
|
|
218
|
+
info(id: string): Promise<WorkflowSkillPack | undefined>;
|
|
219
|
+
/** Same as {@link info}, for a workflow record the caller already holds —
|
|
220
|
+
* `action: list` decorates the whole library and must not re-read
|
|
221
|
+
* workflows.json once per pack. */
|
|
222
|
+
infoFor(workflow: {
|
|
223
|
+
id: string;
|
|
224
|
+
name: string;
|
|
225
|
+
skillDir?: string;
|
|
226
|
+
requireSkill?: boolean;
|
|
227
|
+
}): Promise<WorkflowSkillPack | undefined>;
|
|
228
|
+
/** Attach a pack: create the directory, seed SKILL.md, record the slug. */
|
|
229
|
+
enable(id: string): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
230
|
+
/** Detach the pack from the workflow; the directory stays on disk. */
|
|
231
|
+
disable(id: string): Promise<SkillPackResult<true>>;
|
|
232
|
+
/** Detach and delete the directory. */
|
|
233
|
+
destroy(id: string): Promise<SkillPackResult<true>>;
|
|
234
|
+
/** Toggle the run-time gate. */
|
|
235
|
+
setRequired(id: string, required: boolean): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
236
|
+
/** Create one sub-directory inside the pack. */
|
|
237
|
+
makeDir(id: string, name: string): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
238
|
+
readFile(id: string, path: string): Promise<SkillPackResult<string>>;
|
|
239
|
+
/** One file's raw bytes plus its MIME type, for the panel preview. */
|
|
240
|
+
readRaw(id: string, path: string): Promise<SkillPackResult<{
|
|
241
|
+
bytes: Buffer;
|
|
242
|
+
contentType: string;
|
|
243
|
+
}>>;
|
|
244
|
+
/** Import one uploaded file. Without an explicit bucket the extension picks
|
|
245
|
+
* it (`defaultBucketFor`), and the resolved path comes back to the caller. */
|
|
246
|
+
importFile(id: string, file: string, bytes: Buffer, bucket?: string): Promise<SkillPackResult<{
|
|
247
|
+
path: string;
|
|
248
|
+
pack: WorkflowSkillPack;
|
|
249
|
+
}>>;
|
|
250
|
+
writeFile(id: string, path: string, content: string): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
251
|
+
renameFile(id: string, from: string, to: string): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
252
|
+
deleteFile(id: string, path: string): Promise<SkillPackResult<WorkflowSkillPack>>;
|
|
253
|
+
/** The model-facing body plus resource base. */
|
|
254
|
+
load(id: string): Promise<SkillPackResult<WorkflowSkillBody>>;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Bind the pack directory tree to the workflow library.
|
|
258
|
+
* @param host - the workflow store (its data dir owns the pack root).
|
|
259
|
+
* @returns the operations the tools and routes call.
|
|
260
|
+
*/
|
|
261
|
+
export declare function createWorkflowSkillPacks(host: SkillPackHost): WorkflowSkillPacks;
|
|
262
|
+
export {};
|