@crouton-kit/crouter 0.1.1 → 0.1.3
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/bin/crouter +2 -0
- package/bin/crtr +2 -0
- package/dist/cli.js +36 -4
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +134 -0
- package/dist/commands/doctor.d.ts +2 -0
- package/dist/commands/doctor.js +216 -0
- package/dist/commands/marketplace.d.ts +2 -0
- package/dist/commands/marketplace.js +365 -0
- package/dist/commands/plan.d.ts +2 -0
- package/dist/commands/plan.js +9 -0
- package/dist/commands/plugin.d.ts +2 -0
- package/dist/commands/plugin.js +364 -0
- package/dist/commands/skill.d.ts +2 -0
- package/dist/commands/skill.js +405 -0
- package/dist/commands/spec.d.ts +2 -0
- package/dist/commands/spec.js +9 -0
- package/dist/commands/update.d.ts +4 -0
- package/dist/commands/update.js +140 -0
- package/dist/core/artifact.d.ts +14 -0
- package/dist/core/artifact.js +187 -0
- package/dist/core/auto-update.d.ts +1 -0
- package/dist/core/auto-update.js +86 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +96 -0
- package/dist/core/errors.d.ts +12 -0
- package/dist/core/errors.js +28 -0
- package/dist/core/frontmatter.d.ts +8 -0
- package/dist/core/frontmatter.js +156 -0
- package/dist/core/fs-utils.d.ts +18 -0
- package/dist/core/fs-utils.js +115 -0
- package/dist/core/git.d.ts +18 -0
- package/dist/core/git.js +71 -0
- package/dist/core/manifest.d.ts +5 -0
- package/dist/core/manifest.js +15 -0
- package/dist/core/output.d.ts +35 -0
- package/dist/core/output.js +99 -0
- package/dist/core/resolver.d.ts +28 -0
- package/dist/core/resolver.js +228 -0
- package/dist/core/scope.d.ts +12 -0
- package/dist/core/scope.js +87 -0
- package/dist/prompts/plan.d.ts +1 -0
- package/dist/prompts/plan.js +106 -0
- package/dist/prompts/skill.d.ts +1 -0
- package/dist/prompts/skill.js +49 -0
- package/dist/prompts/spec.d.ts +1 -0
- package/dist/prompts/spec.js +113 -0
- package/dist/types.d.ts +115 -0
- package/dist/types.js +33 -0
- package/package.json +8 -5
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import { homedir } from 'node:os';
|
|
2
|
+
import { existsSync, statSync } from 'node:fs';
|
|
3
|
+
import { join, resolve, dirname } from 'node:path';
|
|
4
|
+
import { CRTR_DIR_NAME } from '../types.js';
|
|
5
|
+
import { usage } from './errors.js';
|
|
6
|
+
let cachedProjectRoot;
|
|
7
|
+
export function userScopeRoot() {
|
|
8
|
+
return join(homedir(), CRTR_DIR_NAME);
|
|
9
|
+
}
|
|
10
|
+
export function findProjectScopeRoot(startDir = process.cwd()) {
|
|
11
|
+
if (cachedProjectRoot !== undefined)
|
|
12
|
+
return cachedProjectRoot;
|
|
13
|
+
const userRoot = userScopeRoot();
|
|
14
|
+
let dir = resolve(startDir);
|
|
15
|
+
while (true) {
|
|
16
|
+
const candidate = join(dir, CRTR_DIR_NAME);
|
|
17
|
+
if (candidate !== userRoot && existsSync(candidate)) {
|
|
18
|
+
try {
|
|
19
|
+
if (statSync(candidate).isDirectory()) {
|
|
20
|
+
cachedProjectRoot = candidate;
|
|
21
|
+
return candidate;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
/* fall through */
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
const parent = dirname(dir);
|
|
29
|
+
if (parent === dir) {
|
|
30
|
+
cachedProjectRoot = null;
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
dir = parent;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export function projectScopeRoot(startDir) {
|
|
37
|
+
return findProjectScopeRoot(startDir);
|
|
38
|
+
}
|
|
39
|
+
export function scopeRoot(scope) {
|
|
40
|
+
return scope === 'user' ? userScopeRoot() : projectScopeRoot();
|
|
41
|
+
}
|
|
42
|
+
export function requireScopeRoot(scope) {
|
|
43
|
+
const root = scopeRoot(scope);
|
|
44
|
+
if (!root) {
|
|
45
|
+
throw usage(`no ${scope} scope available — run \`crtr init\` here or use --scope user`);
|
|
46
|
+
}
|
|
47
|
+
return root;
|
|
48
|
+
}
|
|
49
|
+
export function ensureProjectScopeRoot(startDir = process.cwd()) {
|
|
50
|
+
const found = findProjectScopeRoot(startDir);
|
|
51
|
+
if (found)
|
|
52
|
+
return found;
|
|
53
|
+
// Initialize new project scope at startDir
|
|
54
|
+
const root = join(resolve(startDir), CRTR_DIR_NAME);
|
|
55
|
+
cachedProjectRoot = root;
|
|
56
|
+
return root;
|
|
57
|
+
}
|
|
58
|
+
export function pluginsDir(scope) {
|
|
59
|
+
const root = scopeRoot(scope);
|
|
60
|
+
return root ? join(root, 'plugins') : null;
|
|
61
|
+
}
|
|
62
|
+
export function marketplacesDir(scope) {
|
|
63
|
+
const root = scopeRoot(scope);
|
|
64
|
+
return root ? join(root, 'marketplaces') : null;
|
|
65
|
+
}
|
|
66
|
+
export function resolveScopeArg(scopeArg) {
|
|
67
|
+
if (scopeArg === undefined)
|
|
68
|
+
return 'all';
|
|
69
|
+
const value = scopeArg.toLowerCase();
|
|
70
|
+
if (value === 'user' || value === 'project' || value === 'all')
|
|
71
|
+
return value;
|
|
72
|
+
throw usage(`invalid --scope: ${scopeArg} (expected user|project|all)`);
|
|
73
|
+
}
|
|
74
|
+
export function listScopes(scopeArg) {
|
|
75
|
+
const v = resolveScopeArg(scopeArg);
|
|
76
|
+
if (v === 'all') {
|
|
77
|
+
const out = [];
|
|
78
|
+
if (projectScopeRoot())
|
|
79
|
+
out.push('project');
|
|
80
|
+
out.push('user');
|
|
81
|
+
return out;
|
|
82
|
+
}
|
|
83
|
+
return [v];
|
|
84
|
+
}
|
|
85
|
+
export function resetScopeCache() {
|
|
86
|
+
cachedProjectRoot = undefined;
|
|
87
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function planPrompt(plansDir: string): string;
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
export function planPrompt(plansDir) {
|
|
2
|
+
return `# Planning workflow
|
|
3
|
+
|
|
4
|
+
You are entering a focused planning session. The goal is to produce an
|
|
5
|
+
implementation plan that another agent (or you, in a later turn) can execute
|
|
6
|
+
without re-discovering everything. A plan is a map, not a tutorial.
|
|
7
|
+
|
|
8
|
+
Plans for this directory live at:
|
|
9
|
+
${plansDir}
|
|
10
|
+
|
|
11
|
+
If a relevant prior plan already exists there, read it first.
|
|
12
|
+
|
|
13
|
+
## Phase 1: Initial Understanding
|
|
14
|
+
|
|
15
|
+
Build a comprehensive picture of the user's request and the code involved.
|
|
16
|
+
Actively search for existing functions, utilities, and patterns that can be
|
|
17
|
+
reused — do not propose new code when a suitable implementation already
|
|
18
|
+
exists.
|
|
19
|
+
|
|
20
|
+
- **Launch up to 3 Explore subagents IN PARALLEL** (single message, multiple
|
|
21
|
+
tool calls) to cover the codebase efficiently.
|
|
22
|
+
- Use 1 agent when the task is isolated to known files, the user provided
|
|
23
|
+
specific paths, or the change is small and targeted.
|
|
24
|
+
- Use multiple agents when scope is uncertain, multiple areas of the codebase
|
|
25
|
+
are involved, or you need to understand existing patterns before planning.
|
|
26
|
+
- Quality over quantity — 3 agents maximum; usually 1 is right.
|
|
27
|
+
- When using multiple agents, give each a distinct focus (existing impls,
|
|
28
|
+
related components, test patterns) so they do not duplicate work.
|
|
29
|
+
|
|
30
|
+
## Phase 2: Design
|
|
31
|
+
|
|
32
|
+
Design the implementation approach based on Phase 1 findings.
|
|
33
|
+
|
|
34
|
+
- **Default**: launch at least 1 Plan agent — it validates your understanding
|
|
35
|
+
and surfaces alternatives.
|
|
36
|
+
- **Skip agents** only for truly trivial tasks (typo fixes, single-line
|
|
37
|
+
changes, simple renames).
|
|
38
|
+
- **Multiple agents (up to 3)** for tasks that benefit from different
|
|
39
|
+
perspectives — large refactors, architectural changes, many edge cases.
|
|
40
|
+
|
|
41
|
+
In the Plan agent prompt:
|
|
42
|
+
- Provide comprehensive background context from Phase 1, including filenames
|
|
43
|
+
and code-path traces.
|
|
44
|
+
- Describe requirements and constraints.
|
|
45
|
+
- Request a detailed implementation plan.
|
|
46
|
+
|
|
47
|
+
## Phase 3: Review
|
|
48
|
+
|
|
49
|
+
- Read the critical files identified by agents to deepen your understanding.
|
|
50
|
+
- Ensure the plan aligns with the user's original request.
|
|
51
|
+
- Use **AskUserQuestion** to clarify any remaining questions with the user.
|
|
52
|
+
Bias toward asking when a decision is non-obvious — interrupting once is
|
|
53
|
+
cheaper than building the wrong thing.
|
|
54
|
+
|
|
55
|
+
**Important:** Use AskUserQuestion ONLY to clarify requirements or choose
|
|
56
|
+
between approaches. Never use it to ask the user "is this plan okay?" or
|
|
57
|
+
"should I proceed?" — the save step below is the approval moment.
|
|
58
|
+
|
|
59
|
+
## Phase 4: Final Plan
|
|
60
|
+
|
|
61
|
+
Save the plan with \`crtr plan --name <kebab-case-name>\`. Pipe the markdown
|
|
62
|
+
body in via stdin (heredoc):
|
|
63
|
+
|
|
64
|
+
\`\`\`bash
|
|
65
|
+
crtr plan --name <kebab-case-name> <<'EOF'
|
|
66
|
+
# Plan: <one-line title>
|
|
67
|
+
|
|
68
|
+
## Context
|
|
69
|
+
<why this change is being made — the problem it addresses, what prompted it,
|
|
70
|
+
and the intended outcome>
|
|
71
|
+
|
|
72
|
+
## Recommended approach
|
|
73
|
+
<your chosen approach. Include only the recommendation, not all alternatives.
|
|
74
|
+
Be concise enough to scan, detailed enough to execute.>
|
|
75
|
+
|
|
76
|
+
## Files to modify / create
|
|
77
|
+
- \`path/to/file.ts\` — <what changes>
|
|
78
|
+
- ...
|
|
79
|
+
|
|
80
|
+
## Existing utilities to reuse
|
|
81
|
+
- \`function-name\` from \`path/to/file.ts:LL\` — <why it fits>
|
|
82
|
+
|
|
83
|
+
## Verification
|
|
84
|
+
<how to test the changes end-to-end — run the code, run tests, etc.>
|
|
85
|
+
EOF
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
- Pick a short, descriptive kebab-case name. Names may be nested
|
|
89
|
+
(\`crtr plan --name auth/jwt-refresh\`) — they become subdirectories.
|
|
90
|
+
- The file lands at \`${plansDir}/<name>.md\`.
|
|
91
|
+
- If you are running inside tmux, the saved plan auto-opens in a side pane
|
|
92
|
+
via termrender. No extra step needed.
|
|
93
|
+
|
|
94
|
+
## Phase 5: Done
|
|
95
|
+
|
|
96
|
+
Your turn ends after the save command succeeds. No need to summarize the plan
|
|
97
|
+
in chat — the user can read the file.
|
|
98
|
+
|
|
99
|
+
## See also
|
|
100
|
+
|
|
101
|
+
- \`crtr plan list\` — list saved plans for the current directory
|
|
102
|
+
- \`crtr plan show <name>\` — print the body of a saved plan
|
|
103
|
+
- \`crtr plan edit <name>\` — open a saved plan in \$EDITOR
|
|
104
|
+
- \`crtr plan path [name]\` — absolute path of a plan or the plans directory
|
|
105
|
+
`;
|
|
106
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function skillPrompt(): string;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
export function skillPrompt() {
|
|
2
|
+
return `# Skill workflow
|
|
3
|
+
|
|
4
|
+
\`crtr\` ships skills — markdown reference with frontmatter that you pull on
|
|
5
|
+
demand. When the user's task matches a skill's description, run
|
|
6
|
+
\`crtr skill show <name>\` and apply the guidance. Ambiguous names exit \`4\` —
|
|
7
|
+
disambiguate with \`<plugin>:<name>\`.
|
|
8
|
+
|
|
9
|
+
## Discover
|
|
10
|
+
|
|
11
|
+
\`\`\`
|
|
12
|
+
crtr skill list # one per line: <scope>:<plugin>/<name> — <description>
|
|
13
|
+
crtr skill search <query> # rank by name, description, keywords
|
|
14
|
+
crtr skill grep <pattern> # regex search across SKILL.md bodies
|
|
15
|
+
\`\`\`
|
|
16
|
+
|
|
17
|
+
## Load
|
|
18
|
+
|
|
19
|
+
\`\`\`
|
|
20
|
+
crtr skill show <name> # print SKILL.md body to stdout
|
|
21
|
+
crtr skill show <plugin>:<name> # disambiguate when names collide
|
|
22
|
+
crtr skill path <name> # absolute path to SKILL.md
|
|
23
|
+
crtr skill where <name> # {scope, plugin, path} as JSON
|
|
24
|
+
\`\`\`
|
|
25
|
+
|
|
26
|
+
\`show\` is the default verb: \`crtr skill <name>\` (with no verb) also prints
|
|
27
|
+
the body.
|
|
28
|
+
|
|
29
|
+
## Author
|
|
30
|
+
|
|
31
|
+
\`\`\`
|
|
32
|
+
crtr skill new <plugin>:<name> --description "..." # scaffold a new skill
|
|
33
|
+
crtr skill show authoring-skills # the SKILL.md authoring guide
|
|
34
|
+
\`\`\`
|
|
35
|
+
|
|
36
|
+
## Toggle
|
|
37
|
+
|
|
38
|
+
\`\`\`
|
|
39
|
+
crtr skill enable <name> # clear any disable in the chosen scope
|
|
40
|
+
crtr skill disable <name> # hide from list and agent discovery
|
|
41
|
+
\`\`\`
|
|
42
|
+
|
|
43
|
+
## Exit codes
|
|
44
|
+
|
|
45
|
+
- \`0\` — success
|
|
46
|
+
- \`3\` — skill not found
|
|
47
|
+
- \`4\` — ambiguous name; use \`<plugin>:<name>\`
|
|
48
|
+
`;
|
|
49
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function specPrompt(specsDir: string): string;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
export function specPrompt(specsDir) {
|
|
2
|
+
return `# Spec workflow
|
|
3
|
+
|
|
4
|
+
You are entering a focused spec session. The goal is to produce a design +
|
|
5
|
+
requirements spec — a document describing **what** to build, the shape of the
|
|
6
|
+
solution, and the behaviors it must satisfy. A spec is upstream of a plan: it
|
|
7
|
+
captures decisions, not implementation steps.
|
|
8
|
+
|
|
9
|
+
Specs for this directory live at:
|
|
10
|
+
${specsDir}
|
|
11
|
+
|
|
12
|
+
If a relevant prior spec already exists there, read it first. Treat an
|
|
13
|
+
existing spec as the starting point — extend or revise rather than restart.
|
|
14
|
+
|
|
15
|
+
## Phase 1: Shape
|
|
16
|
+
|
|
17
|
+
Build a comprehensive picture of the problem and the relevant code. Surface
|
|
18
|
+
existing patterns, constraints, and prior decisions.
|
|
19
|
+
|
|
20
|
+
- **Launch up to 3 Explore subagents IN PARALLEL** (single message, multiple
|
|
21
|
+
tool calls) to cover the codebase efficiently.
|
|
22
|
+
- Use 1 agent for narrow, well-scoped problems.
|
|
23
|
+
- Use multiple agents when the spec touches several subsystems or you need
|
|
24
|
+
to compare existing implementations.
|
|
25
|
+
- Quality over quantity — 3 agents maximum.
|
|
26
|
+
|
|
27
|
+
After exploration, draft a high-level design in your head: the shape of the
|
|
28
|
+
solution, the new or changed pieces, the boundaries.
|
|
29
|
+
|
|
30
|
+
## Phase 2: Requirements
|
|
31
|
+
|
|
32
|
+
Translate the shape into concrete behavioral requirements. Each requirement
|
|
33
|
+
should be:
|
|
34
|
+
|
|
35
|
+
- **Testable** — has a clear pass/fail condition.
|
|
36
|
+
- **Behavior-focused** — describes what the system does, not how.
|
|
37
|
+
- **Scoped** — covers one observable behavior.
|
|
38
|
+
|
|
39
|
+
Prefer EARS-style phrasing where it fits (\`When <trigger>, the system shall
|
|
40
|
+
<behavior>\`), but do not force it. Group requirements by capability.
|
|
41
|
+
|
|
42
|
+
You may launch a Plan agent to draft requirements for a specific capability
|
|
43
|
+
in parallel, but for small specs writing them yourself is usually faster.
|
|
44
|
+
|
|
45
|
+
## Phase 3: Deepen
|
|
46
|
+
|
|
47
|
+
- Read the critical files identified during Phase 1 to deepen your
|
|
48
|
+
understanding before locking decisions.
|
|
49
|
+
- Reconcile the requirements against the shape — if a requirement reveals a
|
|
50
|
+
gap in the design, refine the design before saving.
|
|
51
|
+
- Use **AskUserQuestion** for any remaining ambiguities. Bias toward asking
|
|
52
|
+
when a decision is non-obvious or when the user's intent is genuinely
|
|
53
|
+
unclear.
|
|
54
|
+
|
|
55
|
+
**Important:** Use AskUserQuestion ONLY to clarify requirements or choose
|
|
56
|
+
between approaches. Never use it to ask "is this spec okay?" or "should I
|
|
57
|
+
save?" — the save step below is the approval moment.
|
|
58
|
+
|
|
59
|
+
## Phase 4: Save
|
|
60
|
+
|
|
61
|
+
Save the spec with \`crtr spec --name <kebab-case-name>\`. Pipe the markdown
|
|
62
|
+
body in via stdin (heredoc):
|
|
63
|
+
|
|
64
|
+
\`\`\`bash
|
|
65
|
+
crtr spec --name <kebab-case-name> <<'EOF'
|
|
66
|
+
# Spec: <one-line title>
|
|
67
|
+
|
|
68
|
+
## Context
|
|
69
|
+
<the problem this spec addresses, what motivates it, and the intended
|
|
70
|
+
outcome. Include relevant constraints — user goals, stakeholders, deadlines.>
|
|
71
|
+
|
|
72
|
+
## Design
|
|
73
|
+
<the shape of the solution. Components, data flow, key decisions and why
|
|
74
|
+
they were chosen. Reference existing code with \`file_path:line_number\`.>
|
|
75
|
+
|
|
76
|
+
## Requirements
|
|
77
|
+
<grouped behavioral requirements. Each one testable.>
|
|
78
|
+
|
|
79
|
+
### <Capability A>
|
|
80
|
+
- When <trigger>, the system shall <behavior>.
|
|
81
|
+
- ...
|
|
82
|
+
|
|
83
|
+
### <Capability B>
|
|
84
|
+
- ...
|
|
85
|
+
|
|
86
|
+
## Out of scope
|
|
87
|
+
<things explicitly NOT covered, so the next reader knows where the edges
|
|
88
|
+
are.>
|
|
89
|
+
|
|
90
|
+
## Open questions
|
|
91
|
+
<anything you could not resolve. Empty if all decisions are pinned.>
|
|
92
|
+
EOF
|
|
93
|
+
\`\`\`
|
|
94
|
+
|
|
95
|
+
- Pick a short, descriptive kebab-case name. Names may be nested
|
|
96
|
+
(\`crtr spec --name auth/refresh-tokens\`).
|
|
97
|
+
- The file lands at \`${specsDir}/<name>.md\`.
|
|
98
|
+
- If you are running inside tmux, the saved spec auto-opens in a side pane
|
|
99
|
+
via termrender. No extra step needed.
|
|
100
|
+
|
|
101
|
+
## Phase 5: Done
|
|
102
|
+
|
|
103
|
+
Your turn ends after the save command succeeds. No need to summarize the spec
|
|
104
|
+
in chat — the user can read the file.
|
|
105
|
+
|
|
106
|
+
## See also
|
|
107
|
+
|
|
108
|
+
- \`crtr spec list\` — list saved specs for the current directory
|
|
109
|
+
- \`crtr spec show <name>\` — print the body of a saved spec
|
|
110
|
+
- \`crtr spec edit <name>\` — open a saved spec in \$EDITOR
|
|
111
|
+
- \`crtr spec path [name]\` — absolute path of a spec or the specs directory
|
|
112
|
+
`;
|
|
113
|
+
}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
export type Scope = 'user' | 'project';
|
|
2
|
+
export declare const ExitCode: {
|
|
3
|
+
readonly SUCCESS: 0;
|
|
4
|
+
readonly GENERAL: 1;
|
|
5
|
+
readonly USAGE: 2;
|
|
6
|
+
readonly NOT_FOUND: 3;
|
|
7
|
+
readonly AMBIGUOUS: 4;
|
|
8
|
+
readonly NETWORK: 5;
|
|
9
|
+
};
|
|
10
|
+
export type ExitCodeValue = (typeof ExitCode)[keyof typeof ExitCode];
|
|
11
|
+
export declare const SCHEMA_VERSION = 1;
|
|
12
|
+
export interface OwnerRef {
|
|
13
|
+
name?: string;
|
|
14
|
+
email?: string;
|
|
15
|
+
}
|
|
16
|
+
export interface PluginManifest {
|
|
17
|
+
name: string;
|
|
18
|
+
version?: string;
|
|
19
|
+
description?: string;
|
|
20
|
+
source?: string;
|
|
21
|
+
owner?: OwnerRef;
|
|
22
|
+
kinds?: string[];
|
|
23
|
+
}
|
|
24
|
+
export interface MarketplacePluginEntry {
|
|
25
|
+
name: string;
|
|
26
|
+
source: string;
|
|
27
|
+
version?: string;
|
|
28
|
+
description?: string;
|
|
29
|
+
keywords?: string[];
|
|
30
|
+
}
|
|
31
|
+
export interface MarketplaceManifest {
|
|
32
|
+
name: string;
|
|
33
|
+
version?: string;
|
|
34
|
+
owner?: OwnerRef;
|
|
35
|
+
plugins: MarketplacePluginEntry[];
|
|
36
|
+
}
|
|
37
|
+
export interface ConfigMarketplaceEntry {
|
|
38
|
+
url: string;
|
|
39
|
+
ref: string;
|
|
40
|
+
installed_at: string;
|
|
41
|
+
}
|
|
42
|
+
export interface ConfigPluginEntry {
|
|
43
|
+
enabled: boolean;
|
|
44
|
+
source_marketplace?: string;
|
|
45
|
+
version?: string;
|
|
46
|
+
}
|
|
47
|
+
export interface ConfigSkillEntry {
|
|
48
|
+
enabled: boolean;
|
|
49
|
+
}
|
|
50
|
+
export type AutoUpdateMode = 'notify' | 'apply' | false;
|
|
51
|
+
export interface AutoUpdateConfig {
|
|
52
|
+
crtr: AutoUpdateMode;
|
|
53
|
+
content: AutoUpdateMode;
|
|
54
|
+
interval_hours: number;
|
|
55
|
+
}
|
|
56
|
+
export interface ScopeConfig {
|
|
57
|
+
schema_version: number;
|
|
58
|
+
marketplaces: Record<string, ConfigMarketplaceEntry>;
|
|
59
|
+
plugins: Record<string, ConfigPluginEntry>;
|
|
60
|
+
skills: Record<string, ConfigSkillEntry>;
|
|
61
|
+
auto_update: AutoUpdateConfig;
|
|
62
|
+
}
|
|
63
|
+
export interface ScopeState {
|
|
64
|
+
marketplaces: Record<string, {
|
|
65
|
+
last_updated?: string;
|
|
66
|
+
}>;
|
|
67
|
+
plugins: Record<string, {
|
|
68
|
+
last_updated?: string;
|
|
69
|
+
}>;
|
|
70
|
+
last_self_check?: string;
|
|
71
|
+
}
|
|
72
|
+
export interface SkillFrontmatter {
|
|
73
|
+
name: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
keywords?: string[];
|
|
76
|
+
}
|
|
77
|
+
export interface Skill {
|
|
78
|
+
name: string;
|
|
79
|
+
plugin: string;
|
|
80
|
+
scope: Scope;
|
|
81
|
+
path: string;
|
|
82
|
+
pluginRoot: string;
|
|
83
|
+
frontmatter: SkillFrontmatter;
|
|
84
|
+
enabled: boolean;
|
|
85
|
+
disabledIn?: Scope;
|
|
86
|
+
}
|
|
87
|
+
export interface InstalledPlugin {
|
|
88
|
+
name: string;
|
|
89
|
+
scope: Scope;
|
|
90
|
+
root: string;
|
|
91
|
+
manifest: PluginManifest;
|
|
92
|
+
enabled: boolean;
|
|
93
|
+
sourceMarketplace?: string;
|
|
94
|
+
version?: string;
|
|
95
|
+
}
|
|
96
|
+
export interface InstalledMarketplace {
|
|
97
|
+
name: string;
|
|
98
|
+
scope: Scope;
|
|
99
|
+
root: string;
|
|
100
|
+
manifest: MarketplaceManifest;
|
|
101
|
+
url: string;
|
|
102
|
+
ref: string;
|
|
103
|
+
}
|
|
104
|
+
export declare const PLUGIN_MANIFEST_DIR = ".crouter-plugin";
|
|
105
|
+
export declare const PLUGIN_MANIFEST_FILE = "plugin.json";
|
|
106
|
+
export declare const MARKETPLACE_MANIFEST_DIR = ".crouter-marketplace";
|
|
107
|
+
export declare const MARKETPLACE_MANIFEST_FILE = "marketplace.json";
|
|
108
|
+
export declare const CRTR_DIR_NAME = ".crouter";
|
|
109
|
+
export declare const CONFIG_FILE = "config.json";
|
|
110
|
+
export declare const STATE_FILE = "state.json";
|
|
111
|
+
export declare const SKILL_ENTRY_FILE = "SKILL.md";
|
|
112
|
+
export declare const SKILLS_DIR = "skills";
|
|
113
|
+
export declare function defaultScopeConfig(): ScopeConfig;
|
|
114
|
+
export declare function skillConfigKey(plugin: string, name: string): string;
|
|
115
|
+
export declare function defaultScopeState(): ScopeState;
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
export const ExitCode = {
|
|
2
|
+
SUCCESS: 0,
|
|
3
|
+
GENERAL: 1,
|
|
4
|
+
USAGE: 2,
|
|
5
|
+
NOT_FOUND: 3,
|
|
6
|
+
AMBIGUOUS: 4,
|
|
7
|
+
NETWORK: 5,
|
|
8
|
+
};
|
|
9
|
+
export const SCHEMA_VERSION = 1;
|
|
10
|
+
export const PLUGIN_MANIFEST_DIR = '.crouter-plugin';
|
|
11
|
+
export const PLUGIN_MANIFEST_FILE = 'plugin.json';
|
|
12
|
+
export const MARKETPLACE_MANIFEST_DIR = '.crouter-marketplace';
|
|
13
|
+
export const MARKETPLACE_MANIFEST_FILE = 'marketplace.json';
|
|
14
|
+
export const CRTR_DIR_NAME = '.crouter';
|
|
15
|
+
export const CONFIG_FILE = 'config.json';
|
|
16
|
+
export const STATE_FILE = 'state.json';
|
|
17
|
+
export const SKILL_ENTRY_FILE = 'SKILL.md';
|
|
18
|
+
export const SKILLS_DIR = 'skills';
|
|
19
|
+
export function defaultScopeConfig() {
|
|
20
|
+
return {
|
|
21
|
+
schema_version: SCHEMA_VERSION,
|
|
22
|
+
marketplaces: {},
|
|
23
|
+
plugins: {},
|
|
24
|
+
skills: {},
|
|
25
|
+
auto_update: { crtr: 'notify', content: 'notify', interval_hours: 24 },
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function skillConfigKey(plugin, name) {
|
|
29
|
+
return `${plugin}:${name}`;
|
|
30
|
+
}
|
|
31
|
+
export function defaultScopeState() {
|
|
32
|
+
return { marketplaces: {}, plugins: {} };
|
|
33
|
+
}
|
package/package.json
CHANGED
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crouton-kit/crouter",
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"description": "
|
|
3
|
+
"version": "0.1.3",
|
|
4
|
+
"description": "crtr — fast access to skills, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"types": "dist/index.d.ts",
|
|
8
8
|
"bin": {
|
|
9
|
-
"
|
|
9
|
+
"crtr": "bin/crtr",
|
|
10
|
+
"crouter": "bin/crouter"
|
|
10
11
|
},
|
|
11
12
|
"exports": {
|
|
12
13
|
".": {
|
|
@@ -18,12 +19,14 @@
|
|
|
18
19
|
}
|
|
19
20
|
},
|
|
20
21
|
"files": [
|
|
21
|
-
"dist"
|
|
22
|
+
"dist",
|
|
23
|
+
"bin"
|
|
22
24
|
],
|
|
23
25
|
"scripts": {
|
|
24
26
|
"build": "tsc",
|
|
25
27
|
"dev": "tsx src/cli.ts",
|
|
26
|
-
"link": "npm link"
|
|
28
|
+
"link": "npm link",
|
|
29
|
+
"prepublishOnly": "npm run build"
|
|
27
30
|
},
|
|
28
31
|
"repository": {
|
|
29
32
|
"type": "git",
|