faceted-prompting 0.1.0 → 0.2.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.md +155 -16
- package/bin/facet +2 -0
- package/dist/cli/compose-context.d.ts +8 -0
- package/dist/cli/compose-context.d.ts.map +1 -0
- package/dist/cli/compose-context.js +194 -0
- package/dist/cli/compose-context.js.map +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +144 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/install-skill/facets.d.ts +28 -0
- package/dist/cli/install-skill/facets.d.ts.map +1 -0
- package/dist/cli/install-skill/facets.js +160 -0
- package/dist/cli/install-skill/facets.js.map +1 -0
- package/dist/cli/install-skill/flow.d.ts +13 -0
- package/dist/cli/install-skill/flow.d.ts.map +1 -0
- package/dist/cli/install-skill/flow.js +63 -0
- package/dist/cli/install-skill/flow.js.map +1 -0
- package/dist/cli/install-skill/modes.d.ts +27 -0
- package/dist/cli/install-skill/modes.d.ts.map +1 -0
- package/dist/cli/install-skill/modes.js +130 -0
- package/dist/cli/install-skill/modes.js.map +1 -0
- package/dist/cli/install-skill/targets.d.ts +10 -0
- package/dist/cli/install-skill/targets.d.ts.map +1 -0
- package/dist/cli/install-skill/targets.js +27 -0
- package/dist/cli/install-skill/targets.js.map +1 -0
- package/dist/cli/path-guard.d.ts +12 -0
- package/dist/cli/path-guard.d.ts.map +1 -0
- package/dist/cli/path-guard.js +81 -0
- package/dist/cli/path-guard.js.map +1 -0
- package/dist/cli/runner.d.ts +10 -0
- package/dist/cli/runner.d.ts.map +1 -0
- package/dist/cli/runner.js +66 -0
- package/dist/cli/runner.js.map +1 -0
- package/dist/cli/select.d.ts +7 -0
- package/dist/cli/select.d.ts.map +1 -0
- package/dist/cli/select.js +70 -0
- package/dist/cli/select.js.map +1 -0
- package/dist/cli/skill-commands.d.ts +8 -0
- package/dist/cli/skill-commands.d.ts.map +1 -0
- package/dist/cli/skill-commands.js +44 -0
- package/dist/cli/skill-commands.js.map +1 -0
- package/dist/cli/skill-file-ops.d.ts +3 -0
- package/dist/cli/skill-file-ops.d.ts.map +1 -0
- package/dist/cli/skill-file-ops.js +89 -0
- package/dist/cli/skill-file-ops.js.map +1 -0
- package/dist/cli/skill-renderer.d.ts +24 -0
- package/dist/cli/skill-renderer.d.ts.map +1 -0
- package/dist/cli/skill-renderer.js +194 -0
- package/dist/cli/skill-renderer.js.map +1 -0
- package/dist/cli/skill-types.d.ts +31 -0
- package/dist/cli/skill-types.d.ts.map +1 -0
- package/dist/cli/skill-types.js +2 -0
- package/dist/cli/skill-types.js.map +1 -0
- package/dist/cli/types.d.ts +17 -0
- package/dist/cli/types.d.ts.map +1 -0
- package/dist/cli/types.js +2 -0
- package/dist/cli/types.js.map +1 -0
- package/dist/compose-definition.d.ts +3 -0
- package/dist/compose-definition.d.ts.map +1 -0
- package/dist/compose-definition.js +99 -0
- package/dist/compose-definition.js.map +1 -0
- package/dist/compose.d.ts.map +1 -1
- package/dist/compose.js +25 -19
- package/dist/compose.js.map +1 -1
- package/dist/config/index.d.ts +9 -0
- package/dist/config/index.d.ts.map +1 -0
- package/dist/config/index.js +82 -0
- package/dist/config/index.js.map +1 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/init/index.d.ts +17 -0
- package/dist/init/index.d.ts.map +1 -0
- package/dist/init/index.js +197 -0
- package/dist/init/index.js.map +1 -0
- package/dist/output/index.d.ts +10 -0
- package/dist/output/index.d.ts.map +1 -0
- package/dist/output/index.js +67 -0
- package/dist/output/index.js.map +1 -0
- package/dist/prompt-payload.d.ts +8 -0
- package/dist/prompt-payload.d.ts.map +1 -0
- package/dist/prompt-payload.js +24 -0
- package/dist/prompt-payload.js.map +1 -0
- package/dist/types.d.ts +26 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +18 -6
package/README.md
CHANGED
|
@@ -1,17 +1,29 @@
|
|
|
1
1
|
# faceted-prompting
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Faceted Prompting 解説記事](https://nrslib.com/faceted-prompting)
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
Structured prompt composition for LLMs — decompose prompts into reusable facets and compose them into LLM-ready messages.
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
faceted-prompting separates prompt concerns into distinct facets (persona, policy, knowledge, instruction), each with a defined role and message placement. This keeps prompts modular, testable, and maintainable as they grow in complexity.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
9
|
+
## Why Faceted Prompting
|
|
10
|
+
|
|
11
|
+
**Separation of concerns** — Each facet has a single responsibility. Persona defines *who* the agent is, policies define *how* it should behave, knowledge provides *what it needs to know*, and instructions define *what to do*. Changes to one facet don't affect others.
|
|
12
|
+
|
|
13
|
+
**Deterministic placement** — Persona always goes to the system prompt. Policies, knowledge, and instructions always go to the user message. This placement rule is enforced by the library, not left to convention.
|
|
14
|
+
|
|
15
|
+
**Composable** — Facets are plain Markdown files. Mix and match personas, policies, and knowledge across different workflows. Share them as repertoire packages via `@owner/repo/facet-name` scope references.
|
|
16
|
+
|
|
17
|
+
**Framework-independent** — Zero dependencies on any specific AI framework. Use it with Claude, OpenAI, or any LLM provider.
|
|
18
|
+
|
|
19
|
+
## Facet Kinds
|
|
20
|
+
|
|
21
|
+
| Facet | Placement | Role |
|
|
22
|
+
|-------|-----------|------|
|
|
23
|
+
| **Persona** | System prompt | WHO — agent identity and character |
|
|
24
|
+
| **Policy** | User message | HOW — rules, standards, constraints |
|
|
25
|
+
| **Knowledge** | User message | WHAT TO KNOW — domain context, architecture |
|
|
26
|
+
| **Instruction** | User message | WHAT TO DO — the specific task |
|
|
15
27
|
|
|
16
28
|
## Install
|
|
17
29
|
|
|
@@ -19,8 +31,18 @@ Faceted Prompting organizes LLM prompts into distinct facets:
|
|
|
19
31
|
npm install faceted-prompting
|
|
20
32
|
```
|
|
21
33
|
|
|
34
|
+
Global CLI:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
npm install -g faceted-prompting
|
|
38
|
+
facet init
|
|
39
|
+
facet pull-sample
|
|
40
|
+
```
|
|
41
|
+
|
|
22
42
|
## Quick Start
|
|
23
43
|
|
|
44
|
+
### As a library
|
|
45
|
+
|
|
24
46
|
```typescript
|
|
25
47
|
import { compose } from 'faceted-prompting';
|
|
26
48
|
|
|
@@ -34,15 +56,94 @@ const result = compose(
|
|
|
34
56
|
{ contextMaxChars: 8000 },
|
|
35
57
|
);
|
|
36
58
|
|
|
37
|
-
// result.systemPrompt →
|
|
38
|
-
// result.userMessage →
|
|
59
|
+
// result.systemPrompt → "You are a senior TypeScript developer."
|
|
60
|
+
// result.userMessage → policies + knowledge + instruction (in order)
|
|
39
61
|
```
|
|
40
62
|
|
|
63
|
+
### As a CLI
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Create local defaults under ~/.faceted
|
|
67
|
+
facet init
|
|
68
|
+
|
|
69
|
+
# Pull sample facets from TAKT on GitHub
|
|
70
|
+
facet pull-sample
|
|
71
|
+
|
|
72
|
+
# Compose prompts with auto-detected context
|
|
73
|
+
facet compose
|
|
74
|
+
|
|
75
|
+
# Install a skill to Claude Code or Codex
|
|
76
|
+
facet install skill
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`facet init` creates `~/.faceted/` with config, directories, compositions, and templates:
|
|
80
|
+
|
|
81
|
+
```
|
|
82
|
+
~/.faceted/
|
|
83
|
+
├── config.yaml
|
|
84
|
+
├── facets/
|
|
85
|
+
│ ├── persona/ # Persona Markdown files
|
|
86
|
+
│ ├── knowledge/ # Domain knowledge files
|
|
87
|
+
│ ├── policies/ # Policy/rules files
|
|
88
|
+
│ └── compositions/ # Compose definition YAML files
|
|
89
|
+
└── templates/ # Skill templates
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
## CLI Commands
|
|
93
|
+
|
|
94
|
+
| Command | Description |
|
|
95
|
+
|---------|-------------|
|
|
96
|
+
| `facet init` | Create local config, facet directories, compositions, and templates |
|
|
97
|
+
| `facet pull-sample` | Pull sample coding facets from TAKT on GitHub |
|
|
98
|
+
| `facet compose` | Auto-detect context, compose prompts, and write to files |
|
|
99
|
+
| `facet install skill` | Install a skill with facets to Claude Code or Codex |
|
|
100
|
+
|
|
101
|
+
See the [CLI Reference](./docs/cli-reference.md) for details.
|
|
102
|
+
|
|
103
|
+
## Compose Definition
|
|
104
|
+
|
|
105
|
+
Place definition files in `~/.faceted/compositions/*.yaml`:
|
|
106
|
+
|
|
107
|
+
```yaml
|
|
108
|
+
name: release
|
|
109
|
+
description: Release summary composition
|
|
110
|
+
persona: coder
|
|
111
|
+
knowledge:
|
|
112
|
+
- architecture
|
|
113
|
+
policies:
|
|
114
|
+
- quality
|
|
115
|
+
instruction: Summarize release impact.
|
|
116
|
+
order:
|
|
117
|
+
- knowledge
|
|
118
|
+
- policies
|
|
119
|
+
- instruction
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
- `name` and `persona` are required.
|
|
123
|
+
- `order` controls user-message section order (default: `policies` → `knowledge` → `instruction`).
|
|
124
|
+
- `instruction` can be a facet file reference or inline text.
|
|
125
|
+
|
|
126
|
+
## Scope References
|
|
127
|
+
|
|
128
|
+
Reference facets from installed repertoire packages using `@owner/repo/facet-name` syntax:
|
|
129
|
+
|
|
130
|
+
```yaml
|
|
131
|
+
persona: "@nrslib/takt-fullstack/expert-coder"
|
|
132
|
+
knowledge:
|
|
133
|
+
- "@nrslib/takt-fullstack/architecture"
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Scope references resolve to `~/.faceted/repertoire/@{owner}/{repo}/facets/{kind}/{name}.md`.
|
|
137
|
+
|
|
41
138
|
## API
|
|
42
139
|
|
|
43
140
|
### `compose(facets, options)`
|
|
44
141
|
|
|
45
|
-
|
|
142
|
+
Core composition function. Takes a `FacetSet` and `ComposeOptions`, returns a `ComposedPrompt` with `systemPrompt` and `userMessage`.
|
|
143
|
+
|
|
144
|
+
### `composePromptPayload(params)`
|
|
145
|
+
|
|
146
|
+
Higher-level API that composes prompts from a `ComposeDefinition` and also returns `copyFiles` metadata listing the source file paths used.
|
|
46
147
|
|
|
47
148
|
### `FileDataEngine`
|
|
48
149
|
|
|
@@ -57,16 +158,54 @@ const persona = await engine.resolve('personas', 'coder');
|
|
|
57
158
|
|
|
58
159
|
### `CompositeDataEngine`
|
|
59
160
|
|
|
60
|
-
Chains multiple
|
|
161
|
+
Chains multiple `DataEngine` instances with first-match-wins resolution. Useful for layering project-level facets over global defaults.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
import { FileDataEngine, CompositeDataEngine } from 'faceted-prompting';
|
|
165
|
+
|
|
166
|
+
const engine = new CompositeDataEngine([
|
|
167
|
+
new FileDataEngine('./project/facets'), // project-level (wins)
|
|
168
|
+
new FileDataEngine('~/.faceted/facets'), // global fallback
|
|
169
|
+
]);
|
|
170
|
+
```
|
|
61
171
|
|
|
62
172
|
### `renderTemplate(template, vars)`
|
|
63
173
|
|
|
64
|
-
Minimal template engine
|
|
174
|
+
Minimal template engine with `{{variable}}` substitution and `{{#if var}}...{{else}}...{{/if}}` conditionals.
|
|
65
175
|
|
|
66
176
|
### `escapeTemplateChars(str)`
|
|
67
177
|
|
|
68
|
-
Escapes curly braces to prevent template injection.
|
|
178
|
+
Escapes curly braces to full-width Unicode equivalents to prevent template injection in user-supplied content.
|
|
179
|
+
|
|
180
|
+
See the [API Reference](./docs/api-reference.md) for the full API surface.
|
|
181
|
+
|
|
182
|
+
## Project Structure
|
|
183
|
+
|
|
184
|
+
```
|
|
185
|
+
~/.faceted/ # Global config (created on first run)
|
|
186
|
+
├── config.yaml
|
|
187
|
+
├── facets/
|
|
188
|
+
│ ├── persona/
|
|
189
|
+
│ ├── knowledge/
|
|
190
|
+
│ ├── policies/
|
|
191
|
+
│ └── compositions/
|
|
192
|
+
├── templates/ # Skill install templates
|
|
193
|
+
└── repertoire/ # Installed repertoire packages
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
## Documentation
|
|
197
|
+
|
|
198
|
+
| Document | Description |
|
|
199
|
+
|----------|-------------|
|
|
200
|
+
| [Concepts](./docs/concepts.md) | Faceted Prompting design methodology |
|
|
201
|
+
| [CLI Reference](./docs/cli-reference.md) | All commands and options |
|
|
202
|
+
| [API Reference](./docs/api-reference.md) | Library API surface |
|
|
203
|
+
| [Changelog](./CHANGELOG.md) | Version history |
|
|
204
|
+
|
|
205
|
+
## Contributing
|
|
206
|
+
|
|
207
|
+
See [CONTRIBUTING.md](./CONTRIBUTING.md) for details.
|
|
69
208
|
|
|
70
209
|
## License
|
|
71
210
|
|
|
72
|
-
MIT
|
|
211
|
+
MIT — See [LICENSE](./LICENSE) for details.
|
package/bin/facet
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface ComposeContext {
|
|
2
|
+
readonly name: 'coding' | 'frontend' | 'backend';
|
|
3
|
+
readonly knowledgeRefs: readonly string[];
|
|
4
|
+
readonly relatedFiles: readonly string[];
|
|
5
|
+
readonly relatedInstruction?: string;
|
|
6
|
+
}
|
|
7
|
+
export declare function resolveComposeContext(cwd: string): ComposeContext;
|
|
8
|
+
//# sourceMappingURL=compose-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-context.d.ts","sourceRoot":"","sources":["../../src/cli/compose-context.ts"],"names":[],"mappings":"AAuDA,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,QAAQ,GAAG,UAAU,GAAG,SAAS,CAAC;IACjD,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,CAAC;CACtC;AA2JD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,cAAc,CAWjE"}
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
import { execFileSync } from 'node:child_process';
|
|
2
|
+
import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
|
|
3
|
+
import { extname, relative, resolve, sep } from 'node:path';
|
|
4
|
+
import { renderConflictNotice, trimContextContent } from '../truncation.js';
|
|
5
|
+
const CONTEXT_MAX_CHARS = 2000;
|
|
6
|
+
const MAX_FALLBACK_FILES = 12;
|
|
7
|
+
const FRONTEND_EXTENSIONS = new Set([
|
|
8
|
+
'.tsx',
|
|
9
|
+
'.jsx',
|
|
10
|
+
'.css',
|
|
11
|
+
'.scss',
|
|
12
|
+
'.sass',
|
|
13
|
+
'.less',
|
|
14
|
+
'.html',
|
|
15
|
+
'.vue',
|
|
16
|
+
'.svelte',
|
|
17
|
+
]);
|
|
18
|
+
const SOURCE_EXTENSIONS = new Set([
|
|
19
|
+
'.ts',
|
|
20
|
+
'.tsx',
|
|
21
|
+
'.js',
|
|
22
|
+
'.jsx',
|
|
23
|
+
'.mjs',
|
|
24
|
+
'.cjs',
|
|
25
|
+
'.json',
|
|
26
|
+
'.css',
|
|
27
|
+
'.scss',
|
|
28
|
+
'.sass',
|
|
29
|
+
'.less',
|
|
30
|
+
'.html',
|
|
31
|
+
'.vue',
|
|
32
|
+
'.svelte',
|
|
33
|
+
'.java',
|
|
34
|
+
'.kt',
|
|
35
|
+
'.kts',
|
|
36
|
+
'.go',
|
|
37
|
+
'.py',
|
|
38
|
+
'.rb',
|
|
39
|
+
'.rs',
|
|
40
|
+
'.php',
|
|
41
|
+
'.cs',
|
|
42
|
+
'.swift',
|
|
43
|
+
'.sql',
|
|
44
|
+
'.yml',
|
|
45
|
+
'.yaml',
|
|
46
|
+
'.md',
|
|
47
|
+
]);
|
|
48
|
+
const FRONTEND_PATH_PARTS = ['frontend', 'web', 'ui', 'client', 'components', 'pages', 'styles'];
|
|
49
|
+
const BACKEND_PATH_PARTS = ['backend', 'server', 'api', 'db', 'database', 'prisma', 'migrations'];
|
|
50
|
+
const IGNORED_DIRS = new Set(['.git', 'node_modules', 'dist', 'build', 'coverage', '.next']);
|
|
51
|
+
function normalizeRelativePath(cwd, filePath) {
|
|
52
|
+
const resolvedPath = resolve(cwd, filePath);
|
|
53
|
+
const relativePath = relative(cwd, resolvedPath);
|
|
54
|
+
if (relativePath.startsWith(`..${sep}`) || relativePath === '..') {
|
|
55
|
+
throw new Error(`Related file escapes working directory: ${filePath}`);
|
|
56
|
+
}
|
|
57
|
+
return relativePath.length > 0 ? relativePath : filePath;
|
|
58
|
+
}
|
|
59
|
+
function isSourceFile(filePath) {
|
|
60
|
+
return SOURCE_EXTENSIONS.has(extname(filePath).toLowerCase());
|
|
61
|
+
}
|
|
62
|
+
function collectFallbackFiles(cwd, currentDir = cwd, acc = []) {
|
|
63
|
+
const entries = readdirSync(currentDir, { withFileTypes: true })
|
|
64
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
65
|
+
for (const entry of entries) {
|
|
66
|
+
if (acc.length >= MAX_FALLBACK_FILES) {
|
|
67
|
+
return acc;
|
|
68
|
+
}
|
|
69
|
+
if (entry.isDirectory()) {
|
|
70
|
+
if (!IGNORED_DIRS.has(entry.name)) {
|
|
71
|
+
collectFallbackFiles(cwd, resolve(currentDir, entry.name), acc);
|
|
72
|
+
}
|
|
73
|
+
continue;
|
|
74
|
+
}
|
|
75
|
+
const fullPath = resolve(currentDir, entry.name);
|
|
76
|
+
const relativePath = relative(cwd, fullPath);
|
|
77
|
+
if (isSourceFile(relativePath)) {
|
|
78
|
+
acc.push(relativePath);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return acc;
|
|
82
|
+
}
|
|
83
|
+
function detectGitRelatedFiles(cwd) {
|
|
84
|
+
try {
|
|
85
|
+
execFileSync('git', ['rev-parse', '--show-toplevel'], {
|
|
86
|
+
cwd,
|
|
87
|
+
encoding: 'utf-8',
|
|
88
|
+
stdio: 'pipe',
|
|
89
|
+
}).trim();
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return [];
|
|
93
|
+
}
|
|
94
|
+
const collected = new Set();
|
|
95
|
+
const commands = [
|
|
96
|
+
['diff', '--name-only', '--diff-filter=ACMR'],
|
|
97
|
+
['diff', '--name-only', '--cached', '--diff-filter=ACMR'],
|
|
98
|
+
['ls-files', '--others', '--exclude-standard'],
|
|
99
|
+
];
|
|
100
|
+
for (const args of commands) {
|
|
101
|
+
const output = execFileSync('git', args, {
|
|
102
|
+
cwd,
|
|
103
|
+
encoding: 'utf-8',
|
|
104
|
+
stdio: 'pipe',
|
|
105
|
+
});
|
|
106
|
+
for (const line of output.split('\n')) {
|
|
107
|
+
const trimmed = line.trim();
|
|
108
|
+
if (!trimmed)
|
|
109
|
+
continue;
|
|
110
|
+
if (isSourceFile(trimmed)) {
|
|
111
|
+
collected.add(trimmed);
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return Array.from(collected).sort();
|
|
116
|
+
}
|
|
117
|
+
function isFrontendFile(filePath) {
|
|
118
|
+
const normalized = filePath.toLowerCase();
|
|
119
|
+
if (FRONTEND_EXTENSIONS.has(extname(normalized))) {
|
|
120
|
+
return true;
|
|
121
|
+
}
|
|
122
|
+
return FRONTEND_PATH_PARTS.some(part => normalized.includes(`/${part}/`) || normalized.startsWith(`${part}/`));
|
|
123
|
+
}
|
|
124
|
+
function isBackendFile(filePath) {
|
|
125
|
+
const normalized = filePath.toLowerCase();
|
|
126
|
+
return BACKEND_PATH_PARTS.some(part => normalized.includes(`/${part}/`) || normalized.startsWith(`${part}/`));
|
|
127
|
+
}
|
|
128
|
+
function inferPromptName(relatedFiles) {
|
|
129
|
+
const hasFrontend = relatedFiles.some(isFrontendFile);
|
|
130
|
+
const hasBackend = relatedFiles.some(isBackendFile);
|
|
131
|
+
if (hasFrontend && !hasBackend) {
|
|
132
|
+
return 'frontend';
|
|
133
|
+
}
|
|
134
|
+
if (hasBackend && !hasFrontend) {
|
|
135
|
+
return 'backend';
|
|
136
|
+
}
|
|
137
|
+
return 'coding';
|
|
138
|
+
}
|
|
139
|
+
function inferKnowledgeRefs(relatedFiles) {
|
|
140
|
+
const refs = ['architecture'];
|
|
141
|
+
if (relatedFiles.some(isFrontendFile)) {
|
|
142
|
+
refs.push('frontend');
|
|
143
|
+
}
|
|
144
|
+
if (relatedFiles.some(isBackendFile)) {
|
|
145
|
+
refs.push('backend');
|
|
146
|
+
}
|
|
147
|
+
return refs;
|
|
148
|
+
}
|
|
149
|
+
function renderRelatedFileBlock(cwd, relativePath) {
|
|
150
|
+
const absolutePath = resolve(cwd, relativePath);
|
|
151
|
+
if (!existsSync(absolutePath)) {
|
|
152
|
+
return undefined;
|
|
153
|
+
}
|
|
154
|
+
const stats = statSync(absolutePath);
|
|
155
|
+
if (!stats.isFile()) {
|
|
156
|
+
return undefined;
|
|
157
|
+
}
|
|
158
|
+
const content = readFileSync(absolutePath, 'utf-8');
|
|
159
|
+
const prepared = trimContextContent(content, CONTEXT_MAX_CHARS);
|
|
160
|
+
const lines = [
|
|
161
|
+
`## ${relativePath}`,
|
|
162
|
+
'',
|
|
163
|
+
prepared.content,
|
|
164
|
+
'',
|
|
165
|
+
`Source: ${relativePath}`,
|
|
166
|
+
'',
|
|
167
|
+
renderConflictNotice(),
|
|
168
|
+
];
|
|
169
|
+
return lines.join('\n');
|
|
170
|
+
}
|
|
171
|
+
function buildRelatedInstruction(cwd, relatedFiles) {
|
|
172
|
+
if (relatedFiles.length === 0) {
|
|
173
|
+
return undefined;
|
|
174
|
+
}
|
|
175
|
+
const blocks = relatedFiles
|
|
176
|
+
.map(filePath => renderRelatedFileBlock(cwd, filePath))
|
|
177
|
+
.filter((block) => block !== undefined);
|
|
178
|
+
if (blocks.length === 0) {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
return ['# Related Files', '', ...blocks].join('\n\n');
|
|
182
|
+
}
|
|
183
|
+
export function resolveComposeContext(cwd) {
|
|
184
|
+
const relatedFiles = detectGitRelatedFiles(cwd);
|
|
185
|
+
const normalizedFiles = (relatedFiles.length > 0 ? relatedFiles : collectFallbackFiles(cwd))
|
|
186
|
+
.map(filePath => normalizeRelativePath(cwd, filePath));
|
|
187
|
+
return {
|
|
188
|
+
name: inferPromptName(normalizedFiles),
|
|
189
|
+
knowledgeRefs: inferKnowledgeRefs(normalizedFiles),
|
|
190
|
+
relatedFiles: normalizedFiles,
|
|
191
|
+
relatedInstruction: buildRelatedInstruction(cwd, normalizedFiles),
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
//# sourceMappingURL=compose-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compose-context.js","sourceRoot":"","sources":["../../src/cli/compose-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,YAAY,CAAC;AAoHlE,wBAAsB,WAAW,CAC/B,IAAI,EAAE,MAAM,EAAE,EACd,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,cAAc,CAAC,CAkDzB"}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { existsSync } from 'node:fs';
|
|
2
|
+
import { dirname, resolve } from 'node:path';
|
|
3
|
+
import { compose } from '../compose.js';
|
|
4
|
+
import { readFacetedConfig } from '../config/index.js';
|
|
5
|
+
import { initializeFacetedHome, listPullSampleTargetPaths, pullSampleFacets } from '../init/index.js';
|
|
6
|
+
import { formatCombinedOutput, resolveOutputDirectory, writeComposeOutput } from '../output/index.js';
|
|
7
|
+
import { resolveComposeContext } from './compose-context.js';
|
|
8
|
+
import { buildFacetSet, ensureSafeDefinitionName } from './skill-renderer.js';
|
|
9
|
+
import { getSkillPaths, runInstallSkillCommand, } from './skill-commands.js';
|
|
10
|
+
import { shouldOverwrite } from './install-skill/flow.js';
|
|
11
|
+
const USAGE = [
|
|
12
|
+
'Usage: facet <command>',
|
|
13
|
+
'',
|
|
14
|
+
'Commands:',
|
|
15
|
+
' init Initialize local faceted home',
|
|
16
|
+
' pull-sample Pull sample coding facets from TAKT on GitHub',
|
|
17
|
+
' compose Compose facets into a prompt file',
|
|
18
|
+
' install skill Install a skill from a composition',
|
|
19
|
+
].join('\n');
|
|
20
|
+
function ensureCommand(command) {
|
|
21
|
+
if (!command) {
|
|
22
|
+
throw new Error(USAGE);
|
|
23
|
+
}
|
|
24
|
+
return command;
|
|
25
|
+
}
|
|
26
|
+
function ensureSkillSubcommand(command, subcommand) {
|
|
27
|
+
if (subcommand !== 'skill') {
|
|
28
|
+
throw new Error(`Unsupported command: ${command}`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
async function runComposeCommand(options) {
|
|
32
|
+
const { facetsRoot, compositionsDir } = getSkillPaths(options.homeDir);
|
|
33
|
+
const composeContext = resolveComposeContext(options.cwd);
|
|
34
|
+
const definition = {
|
|
35
|
+
name: composeContext.name,
|
|
36
|
+
persona: 'coder',
|
|
37
|
+
policies: ['coding', 'ai-antipattern'],
|
|
38
|
+
knowledge: composeContext.knowledgeRefs,
|
|
39
|
+
instruction: composeContext.relatedInstruction,
|
|
40
|
+
order: ['policies', 'knowledge', 'instruction'],
|
|
41
|
+
};
|
|
42
|
+
const definitionDir = dirname(compositionsDir);
|
|
43
|
+
const facetSet = buildFacetSet({
|
|
44
|
+
definitionDir,
|
|
45
|
+
facetsRoot,
|
|
46
|
+
definition,
|
|
47
|
+
});
|
|
48
|
+
const composed = compose(facetSet, {
|
|
49
|
+
contextMaxChars: 2000,
|
|
50
|
+
userMessageOrder: definition.order,
|
|
51
|
+
});
|
|
52
|
+
const splitSelection = await options.select(['Combined (single file)', 'Split (system + user)'], 'Choose output mode with Up/Down and Enter:');
|
|
53
|
+
const splitSystem = splitSelection === 'Split (system + user)';
|
|
54
|
+
const outputInput = await options.input('Output directory', options.cwd);
|
|
55
|
+
const outputDir = resolveOutputDirectory(outputInput, options.cwd);
|
|
56
|
+
const safeName = ensureSafeDefinitionName(definition.name);
|
|
57
|
+
const outputPlans = splitSystem
|
|
58
|
+
? [
|
|
59
|
+
{
|
|
60
|
+
fileName: `${safeName}.system.md`,
|
|
61
|
+
content: `${composed.systemPrompt}\n`,
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
fileName: `${safeName}.user.md`,
|
|
65
|
+
content: `${composed.userMessage}\n`,
|
|
66
|
+
},
|
|
67
|
+
]
|
|
68
|
+
: [
|
|
69
|
+
{
|
|
70
|
+
fileName: `${safeName}.md`,
|
|
71
|
+
content: formatCombinedOutput(composed),
|
|
72
|
+
},
|
|
73
|
+
];
|
|
74
|
+
const existingPaths = outputPlans
|
|
75
|
+
.map(plan => resolve(outputDir, plan.fileName))
|
|
76
|
+
.filter(path => existsSync(path));
|
|
77
|
+
let overwrite = false;
|
|
78
|
+
if (existingPaths.length > 0) {
|
|
79
|
+
const overwriteAnswer = await options.input(`Output file exists. Overwrite? (${existingPaths.join(', ')}) [y/N]`, 'n');
|
|
80
|
+
if (!shouldOverwrite(overwriteAnswer)) {
|
|
81
|
+
throw new Error(`Output file exists and overwrite was cancelled: ${existingPaths.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
overwrite = true;
|
|
84
|
+
}
|
|
85
|
+
const outputPaths = [];
|
|
86
|
+
for (const plan of outputPlans) {
|
|
87
|
+
outputPaths.push(await writeComposeOutput({
|
|
88
|
+
outputDir,
|
|
89
|
+
fileName: plan.fileName,
|
|
90
|
+
content: plan.content,
|
|
91
|
+
overwrite,
|
|
92
|
+
}));
|
|
93
|
+
}
|
|
94
|
+
if (outputPaths.length === 1) {
|
|
95
|
+
return {
|
|
96
|
+
kind: 'path',
|
|
97
|
+
path: outputPaths[0],
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
return {
|
|
101
|
+
kind: 'paths',
|
|
102
|
+
paths: outputPaths,
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
export async function runFacetCli(args, options) {
|
|
106
|
+
const command = ensureCommand(args[0]);
|
|
107
|
+
const subcommand = args[1];
|
|
108
|
+
if (command === 'init') {
|
|
109
|
+
await initializeFacetedHome({ homeDir: options.homeDir });
|
|
110
|
+
return {
|
|
111
|
+
kind: 'text',
|
|
112
|
+
text: `Initialized: ${resolve(options.homeDir, '.faceted')}`,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
if (command === 'pull-sample') {
|
|
116
|
+
const overlappingPaths = listPullSampleTargetPaths(options.homeDir).filter(path => existsSync(path));
|
|
117
|
+
let overwrite = false;
|
|
118
|
+
if (overlappingPaths.length > 0) {
|
|
119
|
+
const overwriteAnswer = await options.input(`Pull sample will overwrite existing files. Continue? (${overlappingPaths.join(', ')}) [y/N]`, 'n');
|
|
120
|
+
if (!shouldOverwrite(overwriteAnswer)) {
|
|
121
|
+
throw new Error(`Pull sample was cancelled: ${overlappingPaths.join(', ')}`);
|
|
122
|
+
}
|
|
123
|
+
overwrite = true;
|
|
124
|
+
}
|
|
125
|
+
await pullSampleFacets({ homeDir: options.homeDir, overwrite });
|
|
126
|
+
return {
|
|
127
|
+
kind: 'text',
|
|
128
|
+
text: `Pulled sample: ${resolve(options.homeDir, '.faceted')}`,
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
if (command !== 'compose' && command !== 'install') {
|
|
132
|
+
throw new Error(`Unsupported command: ${command}`);
|
|
133
|
+
}
|
|
134
|
+
await readFacetedConfig(options.homeDir);
|
|
135
|
+
if (command === 'compose') {
|
|
136
|
+
return runComposeCommand(options);
|
|
137
|
+
}
|
|
138
|
+
if (command === 'install') {
|
|
139
|
+
ensureSkillSubcommand(command, subcommand);
|
|
140
|
+
return runInstallSkillCommand(options);
|
|
141
|
+
}
|
|
142
|
+
throw new Error(`Unsupported command: ${command}`);
|
|
143
|
+
}
|
|
144
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/cli/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,yBAAyB,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACtG,OAAO,EAAE,oBAAoB,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACtG,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,aAAa,EAAE,wBAAwB,EAAE,MAAM,qBAAqB,CAAC;AAC9E,OAAO,EACL,aAAa,EACb,sBAAsB,GACvB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE1D,MAAM,KAAK,GAAG;IACZ,wBAAwB;IACxB,EAAE;IACF,WAAW;IACX,sDAAsD;IACtD,sEAAsE;IACtE,0DAA0D;IAC1D,2DAA2D;CAC5D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAEb,SAAS,aAAa,CAAC,OAA2B;IAChD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,qBAAqB,CAAC,OAAe,EAAE,UAA8B;IAC5E,IAAI,UAAU,KAAK,OAAO,EAAE,CAAC;QAC3B,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;AACH,CAAC;AAED,KAAK,UAAU,iBAAiB,CAAC,OAAwB;IACvD,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,GAAG,aAAa,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACvE,MAAM,cAAc,GAAG,qBAAqB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG;QACjB,IAAI,EAAE,cAAc,CAAC,IAAI;QACzB,OAAO,EAAE,OAAO;QAChB,QAAQ,EAAE,CAAC,QAAQ,EAAE,gBAAgB,CAAC;QACtC,SAAS,EAAE,cAAc,CAAC,aAAa;QACvC,WAAW,EAAE,cAAc,CAAC,kBAAkB;QAC9C,KAAK,EAAE,CAAC,UAAU,EAAE,WAAW,EAAE,aAAa,CAAU;KACzD,CAAC;IACF,MAAM,aAAa,GAAG,OAAO,CAAC,eAAe,CAAC,CAAC;IAE/C,MAAM,QAAQ,GAAG,aAAa,CAAC;QAC7B,aAAa;QACb,UAAU;QACV,UAAU;KACX,CAAC,CAAC;IAEH,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,EAAE;QACjC,eAAe,EAAE,IAAI;QACrB,gBAAgB,EAAE,UAAU,CAAC,KAAK;KACnC,CAAC,CAAC;IAEH,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,MAAM,CACzC,CAAC,wBAAwB,EAAE,uBAAuB,CAAC,EACnD,4CAA4C,CAC7C,CAAC;IACF,MAAM,WAAW,GAAG,cAAc,KAAK,uBAAuB,CAAC;IAE/D,MAAM,WAAW,GAAG,MAAM,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACzE,MAAM,SAAS,GAAG,sBAAsB,CAAC,WAAW,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC;IACnE,MAAM,QAAQ,GAAG,wBAAwB,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC;IAC3D,MAAM,WAAW,GAAG,WAAW;QAC7B,CAAC,CAAC;YACE;gBACE,QAAQ,EAAE,GAAG,QAAQ,YAAY;gBACjC,OAAO,EAAE,GAAG,QAAQ,CAAC,YAAY,IAAI;aACtC;YACD;gBACE,QAAQ,EAAE,GAAG,QAAQ,UAAU;gBAC/B,OAAO,EAAE,GAAG,QAAQ,CAAC,WAAW,IAAI;aACrC;SACF;QACH,CAAC,CAAC;YACE;gBACE,QAAQ,EAAE,GAAG,QAAQ,KAAK;gBAC1B,OAAO,EAAE,oBAAoB,CAAC,QAAQ,CAAC;aACxC;SACF,CAAC;IACN,MAAM,aAAa,GAAG,WAAW;SAC9B,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;SAC9C,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;IACpC,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,KAAK,CACzC,mCAAmC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EACpE,GAAG,CACJ,CAAC;QAEF,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,CAAC;YACtC,MAAM,IAAI,KAAK,CAAC,mDAAmD,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACjG,CAAC;QACD,SAAS,GAAG,IAAI,CAAC;IACnB,CAAC;IAED,MAAM,WAAW,GAAa,EAAE,CAAC;IACjC,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,WAAW,CAAC,IAAI,CAAC,MAAM,kBAAkB,CAAC;YACxC,SAAS;YACT,QAAQ,EAAE,IAAI,CAAC,QAAQ;YACvB,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,SAAS;SACV,CAAC,CAAC,CAAC;IACN,CAAC;IAED,IAAI,WAAW,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC7B,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,WAAW,CAAC,CAAC,CAAE;SACtB,CAAC;IACJ,CAAC;IAED,OAAO;QACL,IAAI,EAAE,OAAO;QACb,KAAK,EAAE,WAAW;KACnB,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAC/B,IAAc,EACd,OAAwB;IAExB,MAAM,OAAO,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;IACvC,MAAM,UAAU,GAAG,IAAI,CAAC,CAAC,CAAC,CAAC;IAE3B,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;QACvB,MAAM,qBAAqB,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,CAAC,CAAC;QAC1D,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,gBAAgB,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE;SAC7D,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,KAAK,aAAa,EAAE,CAAC;QAC9B,MAAM,gBAAgB,GAAG,yBAAyB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC;QACrG,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChC,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,KAAK,CACzC,yDAAyD,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAC7F,GAAG,CACJ,CAAC;YACF,IAAI,CAAC,eAAe,CAAC,eAAe,CAAC,EAAE,CAAC;gBACtC,MAAM,IAAI,KAAK,CAAC,8BAA8B,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAC/E,CAAC;YACD,SAAS,GAAG,IAAI,CAAC;QACnB,CAAC;QAED,MAAM,gBAAgB,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,SAAS,EAAE,CAAC,CAAC;QAChE,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,IAAI,EAAE,kBAAkB,OAAO,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE;SAC/D,CAAC;IACJ,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QACnD,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;IACrD,CAAC;IAED,MAAM,iBAAiB,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IAEzC,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,OAAO,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACpC,CAAC;IAED,IAAI,OAAO,KAAK,SAAS,EAAE,CAAC;QAC1B,qBAAqB,CAAC,OAAO,EAAE,UAAU,CAAC,CAAC;QAC3C,OAAO,sBAAsB,CAAC,OAAO,CAAC,CAAC;IACzC,CAAC;IAED,MAAM,IAAI,KAAK,CAAC,wBAAwB,OAAO,EAAE,CAAC,CAAC;AACrD,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { buildSkillSections } from '../skill-renderer.js';
|
|
2
|
+
import type { CopyFiles } from '../../types.js';
|
|
3
|
+
type FacetPlaceholderKey = 'persona' | 'knowledges' | 'policies' | 'instructions';
|
|
4
|
+
type FacetTokenValues = Record<FacetPlaceholderKey, string>;
|
|
5
|
+
export type SkillSections = ReturnType<typeof buildSkillSections>;
|
|
6
|
+
export interface FacetPathMap {
|
|
7
|
+
readonly persona: string;
|
|
8
|
+
readonly knowledges: readonly string[];
|
|
9
|
+
readonly policies: readonly string[];
|
|
10
|
+
readonly instructions?: string;
|
|
11
|
+
}
|
|
12
|
+
export declare function buildInlineFacetTokenValues(sections: SkillSections): FacetTokenValues;
|
|
13
|
+
export declare function buildSectionsWithCopiedPaths(sections: SkillSections, facets: FacetPathMap): SkillSections;
|
|
14
|
+
export declare function copyFacetFiles(params: {
|
|
15
|
+
targetDir: string;
|
|
16
|
+
safeSkillName: string;
|
|
17
|
+
copyFiles: CopyFiles;
|
|
18
|
+
literalInstructionBody?: string;
|
|
19
|
+
}): FacetPathMap;
|
|
20
|
+
export declare function applyFacetTokensToPath(params: {
|
|
21
|
+
rootDir: string;
|
|
22
|
+
maxDepth: number;
|
|
23
|
+
tokenValues: FacetTokenValues;
|
|
24
|
+
excludeDirs: readonly string[];
|
|
25
|
+
}): void;
|
|
26
|
+
export declare function parseScanDepth(rawDepth: string): number;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=facets.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"facets.d.ts","sourceRoot":"","sources":["../../../src/cli/install-skill/facets.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAC/D,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAKhD,KAAK,mBAAmB,GAAG,SAAS,GAAG,YAAY,GAAG,UAAU,GAAG,cAAc,CAAC;AAClF,KAAK,gBAAgB,GAAG,MAAM,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;AAE5D,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,kBAAkB,CAAC,CAAC;AAElE,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAC;IACzB,QAAQ,CAAC,UAAU,EAAE,SAAS,MAAM,EAAE,CAAC;IACvC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;CAChC;AA8BD,wBAAgB,2BAA2B,CAAC,QAAQ,EAAE,aAAa,GAAG,gBAAgB,CAOrF;AAQD,wBAAgB,4BAA4B,CAC1C,QAAQ,EAAE,aAAa,EACvB,MAAM,EAAE,YAAY,GACnB,aAAa,CA6Cf;AAED,wBAAgB,cAAc,CAAC,MAAM,EAAE;IACrC,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;IACtB,SAAS,EAAE,SAAS,CAAC;IACrB,sBAAsB,CAAC,EAAE,MAAM,CAAC;CACjC,GAAG,YAAY,CAiDf;AAED,wBAAgB,sBAAsB,CAAC,MAAM,EAAE;IAC7C,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;CAChC,GAAG,IAAI,CAqCP;AAED,wBAAgB,cAAc,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAMvD"}
|