@rse/ase 0.9.46 → 0.9.48
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/dst/ase-artifact.js +3 -1
- package/dst/ase-compat.js +3 -2
- package/dst/ase-config.js +36 -16
- package/dst/ase-diagram.js +10 -15
- package/dst/ase-getopt.js +66 -60
- package/dst/ase-hook.js +51 -77
- package/dst/ase-kv.js +49 -79
- package/dst/ase-log.js +13 -5
- package/dst/ase-markdown.js +12 -2
- package/dst/ase-mcp.js +21 -4
- package/dst/ase-meta.js +1 -1
- package/dst/ase-persona.js +1 -3
- package/dst/ase-service.js +17 -27
- package/dst/ase-setup.js +29 -73
- package/dst/ase-skills.js +1 -1
- package/dst/ase-statusline.js +28 -42
- package/dst/ase-stdio.js +25 -0
- package/dst/ase-task.js +25 -34
- package/dst/ase.js +7 -3
- package/package.json +1 -1
- package/plugin/.claude-plugin/plugin.json +1 -1
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/.github/plugin/plugin.json +1 -1
- package/plugin/etc/stx.conf +2 -2
- package/plugin/meta/ase-skill.md +9 -0
- package/plugin/package.json +1 -1
- package/plugin/skills/{ase-meta-intent → ase-help-intent}/SKILL.md +7 -12
- package/plugin/skills/{ase-meta-intent → ase-help-intent}/help.md +8 -7
- package/plugin/skills/ase-help-skill/SKILL.md +203 -0
- package/plugin/skills/ase-help-skill/catalog.md +60 -0
- package/plugin/skills/ase-help-skill/help.md +83 -0
- package/plugin/skills/ase-task-condense/help.md +3 -3
- package/plugin/skills/ase-task-reboot/help.md +3 -3
- package/plugin/skills/ase-task-view/help.md +3 -3
package/dst/ase-statusline.js
CHANGED
|
@@ -11,7 +11,7 @@ import { InvalidArgumentError } from "commander";
|
|
|
11
11
|
import { execaSync } from "execa";
|
|
12
12
|
import { Chalk } from "chalk";
|
|
13
13
|
import { Config, configSchema, parseScope } from "./ase-config.js";
|
|
14
|
-
import { writeStdout } from "./ase-
|
|
14
|
+
import { readStdin, writeStdout } from "./ase-stdio.js";
|
|
15
15
|
import pkg from "../package.json" with { type: "json" };
|
|
16
16
|
/* forced-color chalk instance: stdout is a pipe under Anthropic Claude Code CLI,
|
|
17
17
|
so chalk auto-detection would yield level 0; force level 1 to keep
|
|
@@ -28,13 +28,6 @@ const parseInteger = (name) => (value) => {
|
|
|
28
28
|
throw new InvalidArgumentError(`${name} must be a non-negative integer`);
|
|
29
29
|
return n;
|
|
30
30
|
};
|
|
31
|
-
/* read stdin into a single string */
|
|
32
|
-
const readStdin = async () => {
|
|
33
|
-
const chunks = [];
|
|
34
|
-
for await (const chunk of process.stdin)
|
|
35
|
-
chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
|
|
36
|
-
return Buffer.concat(chunks).toString("utf8");
|
|
37
|
-
};
|
|
38
31
|
/* detect terminal column width via /dev/tty (stdout is a pipe under Anthropic Claude Code CLI) */
|
|
39
32
|
const detectTermWidth = () => {
|
|
40
33
|
let width = 0;
|
|
@@ -166,6 +159,11 @@ const probeMemory = () => {
|
|
|
166
159
|
return { used: 0, total: 0 };
|
|
167
160
|
}
|
|
168
161
|
};
|
|
162
|
+
/* memoize a zero-argument function, computing its value at most once on first use */
|
|
163
|
+
const memoize = (fn) => {
|
|
164
|
+
let cache = null;
|
|
165
|
+
return () => (cache ??= { value: fn() }).value;
|
|
166
|
+
};
|
|
169
167
|
/* command-line handling */
|
|
170
168
|
export default class StatuslineCommand {
|
|
171
169
|
log;
|
|
@@ -213,8 +211,7 @@ export default class StatuslineCommand {
|
|
|
213
211
|
}
|
|
214
212
|
catch (err) {
|
|
215
213
|
const message = err instanceof Error ? err.message : String(err);
|
|
216
|
-
|
|
217
|
-
process.exit(1);
|
|
214
|
+
throw new Error(`statusline: invalid JSON on stdin: ${message}`);
|
|
218
215
|
}
|
|
219
216
|
/* normalize Copilot CLI's top-level "cwd" into the
|
|
220
217
|
"workspace.current_dir" structure shared with Anthropic Claude Code CLI */
|
|
@@ -263,16 +260,8 @@ export default class StatuslineCommand {
|
|
|
263
260
|
/* lazy memoized probes for cross-renderer values: each is computed at most
|
|
264
261
|
once per run and only when first requested by a renderer (or by the
|
|
265
262
|
post-loop tmux publish for the Config cascade) */
|
|
266
|
-
|
|
267
|
-
const
|
|
268
|
-
if (sessCache === null)
|
|
269
|
-
sessCache = data.session_id ?? "unknown";
|
|
270
|
-
return sessCache;
|
|
271
|
-
};
|
|
272
|
-
let cfgCache = null;
|
|
273
|
-
const getCfg = () => {
|
|
274
|
-
if (cfgCache !== null)
|
|
275
|
-
return cfgCache;
|
|
263
|
+
const getSession = memoize(() => data.session_id ?? "unknown");
|
|
264
|
+
const getCfg = memoize(() => {
|
|
276
265
|
let taskId = process.env.ASE_TASK_ID ?? "";
|
|
277
266
|
let persona = process.env.ASE_PERSONA_STYLE ?? "";
|
|
278
267
|
try {
|
|
@@ -288,21 +277,10 @@ export default class StatuslineCommand {
|
|
|
288
277
|
catch (_e) {
|
|
289
278
|
/* cascade unavailable; keep env-var fallbacks */
|
|
290
279
|
}
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
const getGit = () => {
|
|
296
|
-
if (gitCache === null)
|
|
297
|
-
gitCache = probeGit(data.workspace?.current_dir ?? "");
|
|
298
|
-
return gitCache;
|
|
299
|
-
};
|
|
300
|
-
let memCache = null;
|
|
301
|
-
const getMem = () => {
|
|
302
|
-
if (memCache === null)
|
|
303
|
-
memCache = probeMemory();
|
|
304
|
-
return memCache;
|
|
305
|
-
};
|
|
280
|
+
return { taskId, persona };
|
|
281
|
+
});
|
|
282
|
+
const getGit = memoize(() => probeGit(data.workspace?.current_dir ?? ""));
|
|
283
|
+
const getMem = memoize(() => probeMemory());
|
|
306
284
|
/* identifier to renderer map: each callback fetches its own information
|
|
307
285
|
directly from data (or via the lazy helpers above for shared values) */
|
|
308
286
|
const renderers = {
|
|
@@ -354,10 +332,18 @@ export default class StatuslineCommand {
|
|
|
354
332
|
emit(`${prefix("◔", "context")}${bar} ${pct}%`);
|
|
355
333
|
},
|
|
356
334
|
C: () => {
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
335
|
+
/* probe the live-context fields first and fall back to the
|
|
336
|
+
cumulative ones, so each harness contributes its own view:
|
|
337
|
+
GitHub Copilot CLI reports the live window separately (its
|
|
338
|
+
"total_*" are session sums), whereas Anthropic Claude Code CLI
|
|
339
|
+
folds it into "total_input_tokens". Output tokens stay out --
|
|
340
|
+
"used_percentage" is input-side only. */
|
|
341
|
+
const cw = data.context_window;
|
|
342
|
+
const pct = cw?.used_percentage ?? 0;
|
|
343
|
+
const tokensCur = cw?.current_context_tokens ??
|
|
344
|
+
cw?.last_call_input_tokens ?? cw?.total_input_tokens ?? 0;
|
|
345
|
+
const tokensLim = cw?.displayed_context_limit ?? cw?.context_window_size ??
|
|
346
|
+
(pct > 0 && tokensCur > 0 ? Math.round(tokensCur * 100 / pct) : 0);
|
|
361
347
|
if (tokensLim > 0)
|
|
362
348
|
emit(`${prefix("◆", "tokens")}${c.bold(formatTokens(tokensCur) + "/" + formatTokens(tokensLim))}`);
|
|
363
349
|
},
|
|
@@ -432,11 +418,11 @@ export default class StatuslineCommand {
|
|
|
432
418
|
},
|
|
433
419
|
/* ==== VERSIONS ==== */
|
|
434
420
|
V: () => {
|
|
435
|
-
const
|
|
421
|
+
const toolVersion = data.version ?? "";
|
|
436
422
|
const aseVersion = pkg.version ?? "";
|
|
437
423
|
let version = "";
|
|
438
|
-
if (
|
|
439
|
-
version +=
|
|
424
|
+
if (toolVersion !== "")
|
|
425
|
+
version += `${tool}/${toolVersion}`;
|
|
440
426
|
if (aseVersion !== "")
|
|
441
427
|
version += `${version !== "" ? " " : ""}ase/${aseVersion}`;
|
|
442
428
|
emit(`${prefix("⎈", "version")}${c.bold(version)}`);
|
package/dst/ase-stdio.js
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/*
|
|
2
|
+
** Agentic Software Engineering (ASE)
|
|
3
|
+
** Copyright (c) 2025-2026 Dr. Ralf S. Engelschall <rse@engelschall.com>
|
|
4
|
+
** Licensed under Apache 2.0 <https://spdx.org/licenses/Apache-2.0>
|
|
5
|
+
*/
|
|
6
|
+
import getStdin from "get-stdin";
|
|
7
|
+
/* read the entire stdin payload as a UTF-8 string, treating an
|
|
8
|
+
interactive terminal as empty input so callers never block on a
|
|
9
|
+
user which is not going to type anything */
|
|
10
|
+
export const readStdin = () => {
|
|
11
|
+
return getStdin();
|
|
12
|
+
};
|
|
13
|
+
/* write a string to stdout, awaiting the write callback which only
|
|
14
|
+
fires once the data has been flushed to the underlying pipe, so a
|
|
15
|
+
subsequent "process.exit" cannot truncate the output */
|
|
16
|
+
export const writeStdout = (text) => {
|
|
17
|
+
return new Promise((resolve, reject) => {
|
|
18
|
+
process.stdout.write(text, (err) => {
|
|
19
|
+
if (err)
|
|
20
|
+
reject(err);
|
|
21
|
+
else
|
|
22
|
+
resolve();
|
|
23
|
+
});
|
|
24
|
+
});
|
|
25
|
+
};
|
package/dst/ase-task.js
CHANGED
|
@@ -13,7 +13,7 @@ import { z } from "zod";
|
|
|
13
13
|
import { LRUCache } from "lru-cache";
|
|
14
14
|
import { Config, configSchema, parseScope } from "./ase-config.js";
|
|
15
15
|
import { Markdown } from "./ase-markdown.js";
|
|
16
|
-
import { writeStdout } from "./ase-
|
|
16
|
+
import { readStdin, writeStdout } from "./ase-stdio.js";
|
|
17
17
|
/* reusable functionality: persisted task plans under
|
|
18
18
|
<project>/<basedir>/TASK-<id>.md (driven by the
|
|
19
19
|
"project.artifact.task.{basedir,files}" configuration) */
|
|
@@ -56,11 +56,18 @@ export class Task {
|
|
|
56
56
|
Task.projectRootCache.set(cwd, root);
|
|
57
57
|
return root;
|
|
58
58
|
}
|
|
59
|
+
/* cached task storage specification (TTL-bounded, mirroring the project
|
|
60
|
+
root cache, as each read parses the whole layered YAML config chain) */
|
|
61
|
+
static specCache = new LRUCache({ max: 4, ttl: 2 * 1000 });
|
|
59
62
|
/* read the configured "basedir" anchor and "files" miniglob spec for
|
|
60
63
|
task storage; "basedir" is project-root-relative (POSIX, defaults
|
|
61
64
|
to ".ase/task") and "files" constrains the task filenames
|
|
62
65
|
(defaults to "*.md") */
|
|
63
66
|
static spec(log) {
|
|
67
|
+
const root = Task.projectRoot();
|
|
68
|
+
const cached = Task.specCache.get(root);
|
|
69
|
+
if (cached !== undefined)
|
|
70
|
+
return cached;
|
|
64
71
|
const cfg = new Config("config", configSchema, log);
|
|
65
72
|
cfg.read();
|
|
66
73
|
const read = (key) => {
|
|
@@ -71,8 +78,12 @@ export class Task {
|
|
|
71
78
|
};
|
|
72
79
|
const basedir = (read("project.artifact.task.basedir") || ".ase/task")
|
|
73
80
|
.replace(/\\/g, "/").replace(/^\/+|\/+$/g, "");
|
|
81
|
+
if (basedir.split("/").includes(".."))
|
|
82
|
+
throw new Error(`task: configured "basedir" "${basedir}" must not escape the project root`);
|
|
74
83
|
const files = read("project.artifact.task.files") || "*.md";
|
|
75
|
-
|
|
84
|
+
const result = { basedir, files };
|
|
85
|
+
Task.specCache.set(root, result);
|
|
86
|
+
return result;
|
|
76
87
|
}
|
|
77
88
|
/* resolve the on-disk base directory for task storage */
|
|
78
89
|
static baseDir(log) {
|
|
@@ -89,33 +100,18 @@ export class Task {
|
|
|
89
100
|
}
|
|
90
101
|
/* resolve the on-disk path for a given task id; as a side effect,
|
|
91
102
|
eagerly migrate any legacy <basedir>/<id>/plan.md files to the
|
|
92
|
-
current <basedir>/TASK-<id>.md layout
|
|
93
|
-
|
|
103
|
+
current <basedir>/TASK-<id>.md layout ("migrateAll" is a cheap
|
|
104
|
+
no-op once the store is migrated) */
|
|
94
105
|
static path(log, id) {
|
|
95
106
|
Task.validateId(id);
|
|
96
107
|
Task.enforceFiles(log, id);
|
|
97
|
-
|
|
98
|
-
Task.migrateAll(log);
|
|
108
|
+
Task.migrateAll(log);
|
|
99
109
|
return path.join(Task.baseDir(log), `TASK-${id}.md`);
|
|
100
110
|
}
|
|
101
|
-
/* cheaply check whether any legacy <basedir>/<id>/plan.md file still
|
|
102
|
-
exists in the task base directory and thus needs migration */
|
|
103
|
-
static needsMigration(log) {
|
|
104
|
-
const dir = Task.baseDir(log);
|
|
105
|
-
if (!fs.existsSync(dir))
|
|
106
|
-
return false;
|
|
107
|
-
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
108
|
-
if (!entry.isDirectory() || !/^[A-Za-z0-9_-]+$/.test(entry.name))
|
|
109
|
-
continue;
|
|
110
|
-
if (fs.existsSync(path.join(dir, entry.name, "plan.md")))
|
|
111
|
-
return true;
|
|
112
|
-
}
|
|
113
|
-
return false;
|
|
114
|
-
}
|
|
115
111
|
/* migrate all legacy <basedir>/<id>/plan.md task files to the current
|
|
116
112
|
<basedir>/TASK-<id>.md layout; an existing TASK-<id>.md is never
|
|
117
|
-
overwritten; the
|
|
118
|
-
returns the
|
|
113
|
+
overwritten; the legacy <id>/ directory is removed only if it is
|
|
114
|
+
empty afterwards; returns the migrated task ids in lexicographic order */
|
|
119
115
|
static migrateAll(log) {
|
|
120
116
|
const dir = Task.baseDir(log);
|
|
121
117
|
if (!fs.existsSync(dir))
|
|
@@ -134,7 +130,12 @@ export class Task {
|
|
|
134
130
|
continue;
|
|
135
131
|
}
|
|
136
132
|
fs.renameSync(oldFile, newFile);
|
|
137
|
-
|
|
133
|
+
/* drop the legacy directory, but only if it is really empty */
|
|
134
|
+
const legacyDir = path.dirname(oldFile);
|
|
135
|
+
if (fs.readdirSync(legacyDir).length === 0)
|
|
136
|
+
fs.rmdirSync(legacyDir);
|
|
137
|
+
else
|
|
138
|
+
log.write("warning", `task: keeping non-empty legacy directory "${legacyDir}"`);
|
|
138
139
|
migrated.push(id);
|
|
139
140
|
}
|
|
140
141
|
migrated.sort((a, b) => a.localeCompare(b));
|
|
@@ -187,8 +188,7 @@ export class Task {
|
|
|
187
188
|
/* scan the task base directory (after eager migration) for
|
|
188
189
|
"TASK-<id>.md" files matching the configured "files" miniglob */
|
|
189
190
|
static scan(log) {
|
|
190
|
-
|
|
191
|
-
Task.migrateAll(log);
|
|
191
|
+
Task.migrateAll(log);
|
|
192
192
|
const { basedir, files } = Task.spec(log);
|
|
193
193
|
const dir = path.join(Task.projectRoot(), basedir);
|
|
194
194
|
if (!fs.existsSync(dir))
|
|
@@ -254,15 +254,6 @@ export class Task {
|
|
|
254
254
|
});
|
|
255
255
|
}
|
|
256
256
|
}
|
|
257
|
-
/* read all of stdin as a UTF-8 string */
|
|
258
|
-
const readStdin = () => {
|
|
259
|
-
return new Promise((resolve, reject) => {
|
|
260
|
-
const chunks = [];
|
|
261
|
-
process.stdin.on("data", (chunk) => chunks.push(chunk));
|
|
262
|
-
process.stdin.on("end", () => resolve(Buffer.concat(chunks).toString("utf8")));
|
|
263
|
-
process.stdin.on("error", (err) => reject(err));
|
|
264
|
-
});
|
|
265
|
-
};
|
|
266
257
|
/* CLI command "ase task" */
|
|
267
258
|
export default class TaskCommand {
|
|
268
259
|
log;
|
package/dst/ase.js
CHANGED
|
@@ -59,12 +59,16 @@ const main = async () => {
|
|
|
59
59
|
/* parse program arguments */
|
|
60
60
|
await program.parseAsync(process.argv);
|
|
61
61
|
/* gracefully terminate */
|
|
62
|
-
|
|
62
|
+
await log.close();
|
|
63
|
+
process.exit(process.exitCode ?? 0);
|
|
63
64
|
};
|
|
64
|
-
main().catch((err) => {
|
|
65
|
-
if (err instanceof CommanderError)
|
|
65
|
+
main().catch(async (err) => {
|
|
66
|
+
if (err instanceof CommanderError) {
|
|
67
|
+
await log.close();
|
|
66
68
|
process.exit(err.exitCode);
|
|
69
|
+
}
|
|
67
70
|
const message = err instanceof Error ? err.message : String(err);
|
|
68
71
|
log.write("error", message);
|
|
72
|
+
await log.close();
|
|
69
73
|
process.exit(1);
|
|
70
74
|
});
|
package/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "https://ase.tools",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "https://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.48",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
package/plugin/etc/stx.conf
CHANGED
|
@@ -11,12 +11,12 @@ lint
|
|
|
11
11
|
|
|
12
12
|
# [plugin] build project
|
|
13
13
|
build : lint
|
|
14
|
-
( for name in $(cd skills; ls -1 | grep -v ase-
|
|
14
|
+
( for name in $(cd skills; ls -1 | grep -v ase-help-intent | sort); do
|
|
15
15
|
echo "<skill name=\"$name\">"
|
|
16
16
|
cat skills/$name/help.md | sed -e '/^## SEE ALSO/,$d'
|
|
17
17
|
echo "</skill>"
|
|
18
18
|
done
|
|
19
|
-
) >skills/ase-
|
|
19
|
+
) >skills/ase-help-intent/data.md
|
|
20
20
|
|
|
21
21
|
# [plugin] remove all generated files
|
|
22
22
|
clean
|
package/plugin/meta/ase-skill.md
CHANGED
|
@@ -140,6 +140,15 @@ Skill Sequential Processing
|
|
|
140
140
|
- *IMPORTANT*: For each <step/> you *MUST* use the `TaskUpdate` tool
|
|
141
141
|
for updating its status *during* processing, once a <step/> finished.
|
|
142
142
|
|
|
143
|
+
- *IMPORTANT*: Whenever a skill *stops early* -- because a <step/>
|
|
144
|
+
instructed you to *STOP* processing (on an error, a cancelled
|
|
145
|
+
dialog, a short-circuit branch, or any other early exit) -- you
|
|
146
|
+
*MUST*, *before* emitting the final <template/>, use the `TaskUpdate`
|
|
147
|
+
tool to set the status of *every* still `pending` or `in_progress`
|
|
148
|
+
task of the current <flow/> to `deleted`, so that no task of a
|
|
149
|
+
finished skill remains open. Steps that were *skipped* because their
|
|
150
|
+
`condition` attribute was not met *MUST* be treated the same way.
|
|
151
|
+
|
|
143
152
|
- *IMPORTANT*: You *MUST* *strictly sequentially* execute every <step/> in
|
|
144
153
|
a <flow/>. You *MUST* not implicitly skip any <step/> during
|
|
145
154
|
processing, except you were explicitly requested to do this or the
|
package/plugin/package.json
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
"homepage": "https://ase.tools",
|
|
7
7
|
"repository": { "url": "git+https://github.com/rse/ase.git", "type": "git" },
|
|
8
8
|
"bugs": { "url": "https://github.com/rse/ase/issues" },
|
|
9
|
-
"version": "0.9.
|
|
9
|
+
"version": "0.9.48",
|
|
10
10
|
"license": "Apache-2.0",
|
|
11
11
|
"author": {
|
|
12
12
|
"name": "Dr. Ralf S. Engelschall",
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
name: ase-
|
|
2
|
+
name: ase-help-intent
|
|
3
3
|
argument-hint: "[--help|-h] <intent>"
|
|
4
4
|
description: >
|
|
5
5
|
Match a free-text intent against the accumulated help of all ASE
|
|
@@ -20,12 +20,12 @@ allowed-tools:
|
|
|
20
20
|
@${CLAUDE_SKILL_DIR}/../../meta/ase-dialog.md
|
|
21
21
|
@${CLAUDE_SKILL_DIR}/../../meta/ase-getopt.md
|
|
22
22
|
|
|
23
|
-
<skill name="ase-
|
|
23
|
+
<skill name="ase-help-intent">
|
|
24
24
|
Match an Intent to an ASE Command
|
|
25
25
|
</skill>
|
|
26
26
|
|
|
27
27
|
<expand name="getopt"
|
|
28
|
-
arg1="ase-
|
|
28
|
+
arg1="ase-help-intent"
|
|
29
29
|
arg2="">
|
|
30
30
|
$ARGUMENTS
|
|
31
31
|
</expand>
|
|
@@ -54,7 +54,7 @@ catalog you match <intent/> against:
|
|
|
54
54
|
processing the entire current skill:
|
|
55
55
|
|
|
56
56
|
<template>
|
|
57
|
-
⧉ **ASE**: ✪ skill: **ase-
|
|
57
|
+
⧉ **ASE**: ✪ skill: **ase-help-intent**, ▶ ERROR: expected a `<intent>` argument
|
|
58
58
|
</template>
|
|
59
59
|
</if>
|
|
60
60
|
|
|
@@ -102,16 +102,11 @@ catalog you match <intent/> against:
|
|
|
102
102
|
<template>
|
|
103
103
|
<ase-tpl-head title="SKILL COMMAND PROPOSAL"/>
|
|
104
104
|
|
|
105
|
-
|
|
106
|
-
○ <intent/>
|
|
107
|
-
|
|
108
|
-
● **COMMAND**:
|
|
109
|
-
⌘ `<command/>`
|
|
110
|
-
|
|
111
|
-
● **RATIONALE**:
|
|
112
|
-
○ <rationale/>
|
|
105
|
+
❯ `<command/>`
|
|
113
106
|
|
|
114
107
|
<ase-tpl-foot title="SKILL COMMAND PROPOSAL"/>
|
|
108
|
+
|
|
109
|
+
**RATIONALE**: <rationale/>
|
|
115
110
|
</template>
|
|
116
111
|
|
|
117
112
|
4. *Dispatch Command*:
|
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
|
|
2
2
|
## NAME
|
|
3
3
|
|
|
4
|
-
`ase-
|
|
4
|
+
`ase-help-intent` - Match an Intent to an ASE Command
|
|
5
5
|
|
|
6
6
|
## SYNOPSIS
|
|
7
7
|
|
|
8
|
-
`ase-
|
|
8
|
+
`ase-help-intent`
|
|
9
9
|
[`--help`|`-h`]
|
|
10
10
|
*intent*
|
|
11
11
|
|
|
12
12
|
## DESCRIPTION
|
|
13
13
|
|
|
14
|
-
The `ase-
|
|
14
|
+
The `ase-help-intent` skill matches a free-text *intent* against the
|
|
15
15
|
*accumulated help* of all ASE skills -- the concatenation of every
|
|
16
|
-
skill's `help.md` file into `skills/ase-
|
|
16
|
+
skill's `help.md` file into `skills/ase-help-intent/data.md`, built by
|
|
17
17
|
`npm start build` in `plugin/` -- and generates the *single* best-fitting
|
|
18
18
|
`/ase:ase-xxx-xxx` command that realizes the intent, complete with
|
|
19
19
|
concrete option flags and positional arguments derived from the selected
|
|
@@ -42,15 +42,16 @@ entirely through the intent argument and the interactive dialog.
|
|
|
42
42
|
Route an intent to the matching command and pick from the dialog:
|
|
43
43
|
|
|
44
44
|
```text
|
|
45
|
-
❯ /ase-
|
|
45
|
+
❯ /ase-help-intent lint the TypeScript sources for high-severity issues only
|
|
46
46
|
```
|
|
47
47
|
|
|
48
48
|
Route a planning intent to the matching command:
|
|
49
49
|
|
|
50
50
|
```text
|
|
51
|
-
❯ /ase-
|
|
51
|
+
❯ /ase-help-intent explain how the authentication module works
|
|
52
52
|
```
|
|
53
53
|
|
|
54
54
|
## SEE ALSO
|
|
55
55
|
|
|
56
|
-
[`ase-
|
|
56
|
+
[`ase-help-skill`](../ase-help-skill/help.md), [`ase-meta-proximity`](../ase-meta-proximity/help.md), [`ase-meta-search`](../ase-meta-search/help.md),
|
|
57
|
+
[`ase-code-craft`](../ase-code-craft/help.md).
|