wormajs 0.2.7 → 0.3.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.
|
@@ -15,10 +15,14 @@ const template_1 = require("../template");
|
|
|
15
15
|
* Parse a single line from .wormarc file
|
|
16
16
|
*
|
|
17
17
|
* Supported formats:
|
|
18
|
-
* - `https://xxxx.com/openapi.json` -> generates in src/api, default alova template
|
|
19
|
-
* - `https://yyyy.com/openapi.json, axios` -> generates in src/api2, axios template
|
|
20
|
-
* - `myApi=https://zzzz.com/openapi.json` -> generates in src/myApi,
|
|
21
|
-
* - `
|
|
18
|
+
* - `https://xxxx.com/openapi.json` -> generates in src/api, default alova template, no aiDoc plugin
|
|
19
|
+
* - `https://yyyy.com/openapi.json, axios` -> generates in src/api2, axios template, no aiDoc plugin
|
|
20
|
+
* - `myApi=https://zzzz.com/openapi.json, fetch` -> generates in src/myApi, fetch template, no aiDoc plugin
|
|
21
|
+
* - `https://xxxx.com/openapi.json, alova, cursor` -> alova template, aiDoc installed to `cursor`
|
|
22
|
+
* - `myApi=https://zzzz.com/openapi.json, fetch, cursor, claude-code` -> fetch template, aiDoc installed to both agents
|
|
23
|
+
*
|
|
24
|
+
* The optional third comma-separated segment is the `agent` list for the `aiDoc`
|
|
25
|
+
* plugin. When it is absent, the `aiDoc` plugin is skipped entirely for that line.
|
|
22
26
|
*/
|
|
23
27
|
function parseLine(line) {
|
|
24
28
|
line = line.trim();
|
|
@@ -38,23 +42,17 @@ function parseLine(line) {
|
|
|
38
42
|
return null;
|
|
39
43
|
}
|
|
40
44
|
let outputKey;
|
|
41
|
-
let url;
|
|
42
|
-
let template;
|
|
43
45
|
// Check for key=value format
|
|
44
46
|
const equalIndex = line.indexOf('=');
|
|
45
47
|
if (equalIndex !== -1) {
|
|
46
48
|
outputKey = line.substring(0, equalIndex).trim();
|
|
47
49
|
line = line.substring(equalIndex + 1).trim();
|
|
48
50
|
}
|
|
49
|
-
// Split by comma
|
|
50
|
-
const
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
}
|
|
55
|
-
else {
|
|
56
|
-
url = line.trim();
|
|
57
|
-
}
|
|
51
|
+
// Split by comma into at most three segments: url[, template][, agent]
|
|
52
|
+
const segments = line.split(',').map(s => s.trim()).filter(s => s !== '');
|
|
53
|
+
const url = segments[0] ?? '';
|
|
54
|
+
const template = segments[1];
|
|
55
|
+
const agent = segments[2];
|
|
58
56
|
if (!url) {
|
|
59
57
|
return null;
|
|
60
58
|
}
|
|
@@ -62,6 +60,7 @@ function parseLine(line) {
|
|
|
62
60
|
outputKey,
|
|
63
61
|
url,
|
|
64
62
|
template: template,
|
|
63
|
+
agent,
|
|
65
64
|
};
|
|
66
65
|
}
|
|
67
66
|
/**
|
|
@@ -100,7 +99,7 @@ async function readWormaRc(projectPath) {
|
|
|
100
99
|
if (!parsed) {
|
|
101
100
|
continue;
|
|
102
101
|
}
|
|
103
|
-
const { outputKey, url, template = constant_1.PresetTemplateName.ALOVA } = parsed;
|
|
102
|
+
const { outputKey, url, template = constant_1.PresetTemplateName.ALOVA, agent } = parsed;
|
|
104
103
|
// Determine output folder
|
|
105
104
|
let output;
|
|
106
105
|
if (outputKey) {
|
|
@@ -116,11 +115,18 @@ async function readWormaRc(projectPath) {
|
|
|
116
115
|
if (!template || !PRESET_TEMPLATES[template]) {
|
|
117
116
|
throw logger_1.logger.throwError(`Invalid template: ${template}. Available templates: ${Object.keys(PRESET_TEMPLATES).join(', ')}`);
|
|
118
117
|
}
|
|
118
|
+
// Build plugin list. The aiDoc plugin is only added when an agent is
|
|
119
|
+
// explicitly specified on the line; otherwise no AI skill doc is generated
|
|
120
|
+
// or installed for this entry.
|
|
121
|
+
const plugins = [PRESET_TEMPLATES[template]()];
|
|
122
|
+
if (agent) {
|
|
123
|
+
plugins.push((0, plugins_1.aiDoc)({ agent }));
|
|
124
|
+
}
|
|
119
125
|
// Build generator config
|
|
120
126
|
const generatorConfig = {
|
|
121
127
|
input: url,
|
|
122
128
|
output,
|
|
123
|
-
plugins
|
|
129
|
+
plugins,
|
|
124
130
|
};
|
|
125
131
|
generators.push(generatorConfig);
|
|
126
132
|
}
|
|
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
6
|
exports.aiDoc = aiDoc;
|
|
7
7
|
exports.parseAgentList = parseAgentList;
|
|
8
|
+
exports.parseAgentFile = parseAgentFile;
|
|
8
9
|
const node_child_process_1 = require("node:child_process");
|
|
9
10
|
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
11
|
const node_module_1 = require("node:module");
|
|
@@ -13,12 +14,11 @@ const constant_1 = require("../../constant");
|
|
|
13
14
|
const logger_1 = require("../../helper/logger");
|
|
14
15
|
const template_1 = require("../../template");
|
|
15
16
|
const nodeRequire = (0, node_module_1.createRequire)(__filename);
|
|
16
|
-
const SKILLS_SUPPORTED_AGENTS_URL = 'https://www.npmjs.com/package/skills#supported-agents';
|
|
17
17
|
const prefix = '[plugin: aiDoc]';
|
|
18
18
|
function aiDoc(config) {
|
|
19
19
|
const outputDirName = config?.outputDir ?? 'aidocs';
|
|
20
20
|
const customTemplatePath = config?.template;
|
|
21
|
-
const
|
|
21
|
+
const agentValue = config?.agent;
|
|
22
22
|
let capturedOutput = '';
|
|
23
23
|
let capturedServerName = '';
|
|
24
24
|
return {
|
|
@@ -67,9 +67,9 @@ function aiDoc(config) {
|
|
|
67
67
|
serverName,
|
|
68
68
|
},
|
|
69
69
|
});
|
|
70
|
-
if (
|
|
71
|
-
const
|
|
72
|
-
for (const agent of
|
|
70
|
+
if (agentValue) {
|
|
71
|
+
const agentsToInstall = resolveInstallAgents(agentValue);
|
|
72
|
+
for (const agent of agentsToInstall) {
|
|
73
73
|
installSkill(aidocsDir, agent, projectPath);
|
|
74
74
|
}
|
|
75
75
|
}
|
|
@@ -77,32 +77,20 @@ function aiDoc(config) {
|
|
|
77
77
|
};
|
|
78
78
|
}
|
|
79
79
|
/**
|
|
80
|
-
* Resolve the
|
|
80
|
+
* Resolve the list of coding agents to install the generated skill into.
|
|
81
81
|
*
|
|
82
|
-
*
|
|
83
|
-
* `
|
|
84
|
-
*
|
|
82
|
+
* @param agent the raw `agent` config value
|
|
83
|
+
* - `SkillAgent` / `SkillAgent[]`: used directly as the target agent(s).
|
|
84
|
+
* - `string`: parsed as a comma (English or Chinese) separated agent list,
|
|
85
|
+
* e.g. `"cursor"` or `"cursor, claude-code"`.
|
|
85
86
|
*
|
|
86
|
-
*
|
|
87
|
-
*
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* If `agent` is missing or empty, an error is thrown with guidance.
|
|
87
|
+
* The agent list is no longer read from `node_modules/.worma/skills.local`.
|
|
88
|
+
* Instead, callers pass the agent(s) explicitly via the `agent`
|
|
89
|
+
* option (optionally sourced from their own config file via `parseAgentFile`).
|
|
91
90
|
*/
|
|
92
|
-
function
|
|
93
|
-
const
|
|
94
|
-
|
|
95
|
-
createEnvLocalFile(envFilePath);
|
|
96
|
-
ensureGitIgnoreLocal(projectPath);
|
|
97
|
-
throw logger_1.logger.throwError(`${prefix}Created .env.local at project root. Please set the coding agent you are using, e.g. agent=cursor or multiple agents comma-separated: agent=cursor,claude-code. Supported agents list: ${SKILLS_SUPPORTED_AGENTS_URL}`);
|
|
98
|
-
}
|
|
99
|
-
const content = node_fs_1.default.readFileSync(envFilePath, 'utf-8');
|
|
100
|
-
const raw = parseEnvValue(content, 'agent') ?? '';
|
|
101
|
-
const agents = parseAgentList(raw);
|
|
102
|
-
if (agents.length === 0) {
|
|
103
|
-
throw logger_1.logger.throwError(`${prefix}Missing "agent" in .env.local at project root. Please set the coding agent you are using, e.g. agent=cursor or multiple agents comma-separated: agent=cursor,claude-code. Supported agents list: ${SKILLS_SUPPORTED_AGENTS_URL}`);
|
|
104
|
-
}
|
|
105
|
-
return { agents };
|
|
91
|
+
function resolveInstallAgents(agent) {
|
|
92
|
+
const raw = Array.isArray(agent) ? agent.join(',') : agent;
|
|
93
|
+
return parseAgentList(raw);
|
|
106
94
|
}
|
|
107
95
|
/**
|
|
108
96
|
* Parse an agent string into a deduplicated list of trimmed agent names.
|
|
@@ -155,47 +143,45 @@ function installSkill(skillPath, agent, projectPath) {
|
|
|
155
143
|
throw logger_1.logger.throwError(error);
|
|
156
144
|
}
|
|
157
145
|
}
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
const
|
|
183
|
-
for (const line of lines) {
|
|
146
|
+
/**
|
|
147
|
+
* Parse a `key=value` configuration file (same format as an environment file).
|
|
148
|
+
*
|
|
149
|
+
* Lines starting with `#` are treated as comments and ignored; blank lines and
|
|
150
|
+
* lines without `=` are skipped. Surrounding single/double quotes around values
|
|
151
|
+
* are stripped. Returns a map of keys to their (string) values.
|
|
152
|
+
*
|
|
153
|
+
* When `filePath` is omitted, the file is read from `.wormaagent.local` in the
|
|
154
|
+
* current working directory (project root).
|
|
155
|
+
*
|
|
156
|
+
* This makes it easy to keep the target coding agent(s) in a config file and
|
|
157
|
+
* feed them into the `agent` option:
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* ```ts
|
|
161
|
+
* // .wormaagent.local -> agent=cursor, claude-code
|
|
162
|
+
* const cfg = parseAgentFile() // reads ./.wormaagent.local by default
|
|
163
|
+
* aiDoc({ agent: cfg.agent })
|
|
164
|
+
* ```
|
|
165
|
+
*/
|
|
166
|
+
function parseAgentFile(filePath) {
|
|
167
|
+
const target = filePath ?? node_path_1.default.resolve(process.cwd(), '.wormaagent.local');
|
|
168
|
+
const content = node_fs_1.default.readFileSync(target, 'utf-8');
|
|
169
|
+
const result = {};
|
|
170
|
+
for (const line of content.split(/\r?\n/)) {
|
|
184
171
|
const trimmed = line.trim();
|
|
185
|
-
if (trimmed.startsWith('#') || !trimmed.includes('=')) {
|
|
172
|
+
if (trimmed === '' || trimmed.startsWith('#') || !trimmed.includes('=')) {
|
|
186
173
|
continue;
|
|
187
174
|
}
|
|
188
175
|
const eqIndex = trimmed.indexOf('=');
|
|
189
|
-
const
|
|
190
|
-
let
|
|
176
|
+
const key = trimmed.slice(0, eqIndex).trim();
|
|
177
|
+
let value = trimmed.slice(eqIndex + 1).trim();
|
|
191
178
|
// Remove surrounding quotes if present
|
|
192
|
-
if ((
|
|
193
|
-
|
|
194
|
-
}
|
|
195
|
-
if (k === key) {
|
|
196
|
-
return v;
|
|
179
|
+
if ((value.startsWith('"') && value.endsWith('"')) || (value.startsWith('\'') && value.endsWith('\''))) {
|
|
180
|
+
value = value.slice(1, -1);
|
|
197
181
|
}
|
|
182
|
+
if (key)
|
|
183
|
+
result[key] = value;
|
|
198
184
|
}
|
|
199
|
-
return
|
|
185
|
+
return result;
|
|
200
186
|
}
|
|
201
187
|
exports.default = aiDoc;
|
|
@@ -18,7 +18,7 @@ generator: [
|
|
|
18
18
|
* swagger platform plugin: auto-resolves OpenAPI file URLs from the base URL.
|
|
19
19
|
* The base URL is passed as the plugin argument (not config.input).
|
|
20
20
|
*/
|
|
21
|
-
plugins: [swagger('http://localhost:3000'), aiDoc({
|
|
21
|
+
plugins: [swagger('http://localhost:3000'), aiDoc({ agent: 'codex' }), {{{templateCall}}}],
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* the mediaType of the generated response data. default is `application/json`
|
package/package.json
CHANGED
package/typings/plugins.d.ts
CHANGED
|
@@ -424,10 +424,30 @@ export interface TemplateData {
|
|
|
424
424
|
* });
|
|
425
425
|
*/
|
|
426
426
|
export declare function createPlugin<T extends any[]>(plugin: (...args: T) => ApiPlugin): (...args: T) => ApiPlugin;
|
|
427
|
+
/**
|
|
428
|
+
* Coding agents that the generated skill can be installed into.
|
|
429
|
+
*
|
|
430
|
+
* The `skills` package (`https://www.npmjs.com/package/skills`) is CLI-only and
|
|
431
|
+
* ships no TypeScript types, so this union mirrors the agent names it supports
|
|
432
|
+
* (its documented "supported agents" list). The transitive `@vercel/detect-agent`
|
|
433
|
+
* package does export a `KnownAgentNames` type, but it only covers a small subset
|
|
434
|
+
* of agents (e.g. it is missing `claude-code` and `windsurf`), so it cannot be
|
|
435
|
+
* reused directly here.
|
|
436
|
+
*/
|
|
437
|
+
export type SkillAgent = "aider-desk" | "amp" | "antigravity" | "antigravity-cli" | "astrbot" | "augment" | "autohand-code" | "bob" | "claude-code" | "cline" | "codearts-agent" | "codebuddy" | "codemaker" | "codestudio" | "codex" | "command-code" | "continue" | "cortex" | "crush" | "cursor" | "deepagents" | "devin" | "dexto" | "droid" | "eve" | "firebender" | "forgecode" | "gemini-cli" | "github-copilot" | "goose" | "hermes-agent" | "iflow-cli" | "inference-sh" | "jazz" | "junie" | "kilo" | "kiro-cli" | "kimi-code-cli" | "kode" | "lingma" | "loaf" | "mcpjam" | "mistral-vibe" | "moxby" | "mux" | "ona" | "opencode" | "openhands" | "openclaw" | "pi" | "pochi" | "promptscript" | "qoder" | "qoder-cn" | "qwen-code" | "reasonix" | "replit" | "rovodev" | "roo" | "tabnine-cli" | "terramind" | "tinycloud" | "trae" | "trae-cn" | "universal" | "warp" | "windsurf" | "zed" | "zencoder" | "zenflow" | "neovate" | "adal";
|
|
427
438
|
export interface AiDocConfig {
|
|
428
439
|
template?: string;
|
|
429
440
|
outputDir?: string;
|
|
430
|
-
|
|
441
|
+
/**
|
|
442
|
+
* Which coding agent(s) to install the generated skill into.
|
|
443
|
+
* - omitted: do NOT install the skill.
|
|
444
|
+
* - `SkillAgent` / `SkillAgent[]`: install to the given agent(s) directly.
|
|
445
|
+
* - `string`: comma (English or Chinese) separated agent names, used directly
|
|
446
|
+
* as the target agent(s), e.g. `"cursor"` or `"cursor, claude-code"`.
|
|
447
|
+
* This is handy when the agent list comes from a config file parsed via
|
|
448
|
+
* `parseAgentFile`, e.g. `aiDoc({ agent: parseAgentFile('.myrc').agent })`.
|
|
449
|
+
*/
|
|
450
|
+
agent?: SkillAgent | (SkillAgent | (string & {}))[] | (string & {});
|
|
431
451
|
}
|
|
432
452
|
export declare function aiDoc(config?: AiDocConfig): ApiPlugin;
|
|
433
453
|
/**
|
|
@@ -438,6 +458,27 @@ export declare function aiDoc(config?: AiDocConfig): ApiPlugin;
|
|
|
438
458
|
* either side. Empty entries are ignored.
|
|
439
459
|
*/
|
|
440
460
|
export declare function parseAgentList(raw: string): string[];
|
|
461
|
+
/**
|
|
462
|
+
* Parse a `key=value` configuration file (same format as an environment file).
|
|
463
|
+
*
|
|
464
|
+
* Lines starting with `#` are treated as comments and ignored; blank lines and
|
|
465
|
+
* lines without `=` are skipped. Surrounding single/double quotes around values
|
|
466
|
+
* are stripped. Returns a map of keys to their (string) values.
|
|
467
|
+
*
|
|
468
|
+
* When `filePath` is omitted, the file is read from `.wormaagent.local` in the
|
|
469
|
+
* current working directory (project root).
|
|
470
|
+
*
|
|
471
|
+
* This makes it easy to keep the target coding agent(s) in a config file and
|
|
472
|
+
* feed them into the `agent` option:
|
|
473
|
+
*
|
|
474
|
+
* @example
|
|
475
|
+
* ```ts
|
|
476
|
+
* // .wormaagent.local -> agent=cursor, claude-code
|
|
477
|
+
* const cfg = parseAgentFile() // reads ./.wormaagent.local by default
|
|
478
|
+
* aiDoc({ agent: cfg.agent })
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
export declare function parseAgentFile(filePath?: string): Record<string, string>;
|
|
441
482
|
export type ScopeType = "ALL" | "SELECTED_ENDPOINTS" | "SELECTED_TAGS" | "SELECTED_FOLDERS";
|
|
442
483
|
export interface APIFoxBody {
|
|
443
484
|
scope?: {
|