@elizaos/prompts 2.0.0-alpha.98 → 2.0.11-beta.7
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 +34 -92
- package/package.json +18 -15
- package/scripts/check-secrets.js +93 -57
- package/scripts/file-utils.js +13 -0
- package/scripts/generate-action-docs.js +152 -478
- package/scripts/generate-plugin-action-spec.js +1135 -148
- package/scripts/prompt-compression.js +171 -0
- package/src/index.ts +1271 -0
- package/dist/python/__init__.py +0 -2
- package/dist/python/prompts.py +0 -598
- package/dist/rust/mod.rs +0 -3
- package/dist/rust/prompts.rs +0 -572
- package/dist/typescript/index.d.ts +0 -42
- package/dist/typescript/index.ts +0 -612
- package/prompts/autonomy_continuous_continue.txt +0 -15
- package/prompts/autonomy_continuous_first.txt +0 -13
- package/prompts/autonomy_task_continue.txt +0 -17
- package/prompts/autonomy_task_first.txt +0 -14
- package/prompts/choose_option.txt +0 -25
- package/prompts/image_description.txt +0 -29
- package/prompts/image_generation.txt +0 -25
- package/prompts/message_handler.txt +0 -105
- package/prompts/multi_step_decision.txt +0 -52
- package/prompts/multi_step_summary.txt +0 -44
- package/prompts/option_extraction.txt +0 -29
- package/prompts/post_creation.txt +0 -50
- package/prompts/reflection.txt +0 -31
- package/prompts/reflection_evaluator.txt +0 -62
- package/prompts/reply.txt +0 -31
- package/prompts/should_respond.txt +0 -40
- package/prompts/update_entity.txt +0 -31
- package/prompts/update_settings.txt +0 -30
- package/scripts/generate-plugin-prompts.js +0 -306
- package/scripts/generate.js +0 -279
package/README.md
CHANGED
|
@@ -1,63 +1,52 @@
|
|
|
1
1
|
# @elizaos/prompts
|
|
2
2
|
|
|
3
|
-
Shared prompt templates
|
|
3
|
+
Shared prompt templates and action specs for elizaOS.
|
|
4
4
|
|
|
5
5
|
## Overview
|
|
6
6
|
|
|
7
|
-
This package
|
|
7
|
+
This package is the single source of truth for prompt templates used by the runtime. Prompts are authored directly in `src/index.ts`.
|
|
8
8
|
|
|
9
9
|
## Structure
|
|
10
10
|
|
|
11
11
|
```
|
|
12
12
|
packages/prompts/
|
|
13
|
-
├──
|
|
14
|
-
│
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
├──
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
│ ├── typescript/ # TypeScript exports
|
|
22
|
-
│ ├── python/ # Python module
|
|
23
|
-
│ └── rust/ # Rust source
|
|
24
|
-
└── package.json
|
|
13
|
+
├── src/
|
|
14
|
+
│ └── index.ts # TypeScript prompt template exports
|
|
15
|
+
├── specs/ # Merged action/provider specs (JSON) + generated plugins.generated.json
|
|
16
|
+
└── scripts/ # Spec + docs generators
|
|
17
|
+
├── generate-action-docs.js
|
|
18
|
+
├── generate-plugin-action-spec.js
|
|
19
|
+
├── prompt-compression.js
|
|
20
|
+
└── check-secrets.js
|
|
25
21
|
```
|
|
26
22
|
|
|
27
23
|
## Template Syntax
|
|
28
24
|
|
|
29
|
-
|
|
25
|
+
Prompts use Handlebars-style variables:
|
|
30
26
|
|
|
31
|
-
- `{{variableName}}` -
|
|
32
|
-
- `{{#each items}}...{{/each}}` -
|
|
33
|
-
- `{{#if condition}}...{{/if}}` -
|
|
27
|
+
- `{{variableName}}` - simple variable substitution
|
|
28
|
+
- `{{#each items}}...{{/each}}` - iteration
|
|
29
|
+
- `{{#if condition}}...{{/if}}` - conditional
|
|
34
30
|
|
|
35
|
-
|
|
31
|
+
Use camelCase for variables (`{{agentName}}`, `{{providers}}`, `{{recentMessages}}`).
|
|
36
32
|
|
|
37
|
-
|
|
33
|
+
## Plugin-local `prompts/*.json` (under `plugins/**`)
|
|
38
34
|
|
|
39
|
-
- `
|
|
40
|
-
- `{{providers}}` - Provider context
|
|
41
|
-
- `{{recentMessages}}` - Recent conversation messages
|
|
35
|
+
Some plugins keep **hand-edited** `actions.json` / `evaluators.json` / `providers.json` next to their source. Those files feed **per-plugin codegen** (for example `generated/specs/spec-helpers.ts` via each plugin’s own workflow). They are **not** inputs to `scripts/generate-plugin-action-spec.js`, which instead scans `plugins/**/*.ts` for `export const …: Action` blocks and writes `specs/actions/plugins.generated.json`.
|
|
42
36
|
|
|
43
37
|
## Building
|
|
44
38
|
|
|
45
39
|
```bash
|
|
46
|
-
#
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
# Build specific target
|
|
50
|
-
npm run build:typescript
|
|
51
|
-
npm run build:python
|
|
52
|
-
npm run build:rust
|
|
40
|
+
# Generate plugin action spec + action docs
|
|
41
|
+
bun run build
|
|
53
42
|
```
|
|
54
43
|
|
|
55
44
|
## Usage
|
|
56
45
|
|
|
57
|
-
|
|
46
|
+
Runtime code imports the templates through `@elizaos/core`, which re-exports them and provides `composePrompt` to fill the `{{...}}` placeholders:
|
|
58
47
|
|
|
59
48
|
```typescript
|
|
60
|
-
import { REPLY_TEMPLATE,
|
|
49
|
+
import { REPLY_TEMPLATE, composePrompt } from "@elizaos/core";
|
|
61
50
|
|
|
62
51
|
const prompt = composePrompt({
|
|
63
52
|
state: { agentName: "Alice" },
|
|
@@ -65,78 +54,31 @@ const prompt = composePrompt({
|
|
|
65
54
|
});
|
|
66
55
|
```
|
|
67
56
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
```python
|
|
71
|
-
from elizaos.prompts import REPLY_TEMPLATE, CHOOSE_OPTION_TEMPLATE
|
|
72
|
-
|
|
73
|
-
prompt = compose_prompt(state={'agentName': 'Alice'}, template=REPLY_TEMPLATE)
|
|
74
|
-
```
|
|
75
|
-
|
|
76
|
-
### Rust
|
|
77
|
-
|
|
78
|
-
```rust
|
|
79
|
-
use elizaos_prompts::{REPLY_TEMPLATE, CHOOSE_OPTION_TEMPLATE};
|
|
80
|
-
|
|
81
|
-
let prompt = compose_prompt(&state, REPLY_TEMPLATE);
|
|
82
|
-
```
|
|
57
|
+
Import directly from `@elizaos/prompts` only inside this package's tooling and tests.
|
|
83
58
|
|
|
84
59
|
## Adding New Prompts
|
|
85
60
|
|
|
86
|
-
1.
|
|
87
|
-
2.
|
|
88
|
-
3. Run `npm run build` to generate native code
|
|
89
|
-
4. The prompt will be exported as `MY_NEW_ACTION_TEMPLATE` in all languages
|
|
90
|
-
|
|
91
|
-
## Plugin Prompts
|
|
92
|
-
|
|
93
|
-
Plugins can use the same prompt system! See [README-PLUGIN-PROMPTS.md](./README-PLUGIN-PROMPTS.md) for details on how to set up prompts in your plugin.
|
|
94
|
-
|
|
95
|
-
The `scripts/generate-plugin-prompts.js` utility can be used by any plugin to generate TypeScript, Python, and Rust exports from `.txt` prompt templates.
|
|
61
|
+
1. Add a `camelCaseTemplate` string export in `src/index.ts`.
|
|
62
|
+
2. Add the paired `UPPER_SNAKE_CASE_TEMPLATE` export.
|
|
96
63
|
|
|
97
64
|
## Template Guidelines
|
|
98
65
|
|
|
99
|
-
1. **Start with a task description**
|
|
100
|
-
2. **Include providers placeholder**
|
|
101
|
-
3. **Use
|
|
102
|
-
4. **Add clear instructions**
|
|
103
|
-
5. **End with output format**
|
|
66
|
+
1. **Start with a task description** — begin prompts with `# Task:` to state the objective.
|
|
67
|
+
2. **Include providers placeholder** — use `{{providers}}` where provider context should be injected.
|
|
68
|
+
3. **Use JSON output format** — standardize on JSON response format for consistent parsing.
|
|
69
|
+
4. **Add clear instructions** — explicit instructions for the LLM.
|
|
70
|
+
5. **End with output format** — always specify the expected output format.
|
|
104
71
|
|
|
105
|
-
|
|
72
|
+
## Security & Privacy
|
|
106
73
|
|
|
107
|
-
|
|
108
|
-
# Task: Generate dialog for the character {{agentName}}.
|
|
109
|
-
|
|
110
|
-
{{providers}}
|
|
111
|
-
|
|
112
|
-
# Instructions: Write the next message for {{agentName}}.
|
|
113
|
-
|
|
114
|
-
Respond using XML format like this:
|
|
115
|
-
<response>
|
|
116
|
-
<thought>Your thought here</thought>
|
|
117
|
-
<text>Your message here</text>
|
|
118
|
-
</response>
|
|
119
|
-
|
|
120
|
-
IMPORTANT: Your response must ONLY contain the <response></response> XML block above.
|
|
121
|
-
```
|
|
122
|
-
|
|
123
|
-
## Security & Privacy Guidance (SOC2-aligned)
|
|
124
|
-
|
|
125
|
-
- **Do not embed real secrets** in prompt templates. Prompts are source-controlled and often distributed.
|
|
74
|
+
- **Do not embed real secrets** in prompt templates. Prompts are source-controlled.
|
|
126
75
|
- **Avoid including PII** (emails, phone numbers, addresses, IDs) in templates or examples.
|
|
127
|
-
- Prefer placeholders (e.g., `{{apiKey}}`, `{{userEmail}}`) and
|
|
76
|
+
- Prefer placeholders (e.g., `{{apiKey}}`, `{{userEmail}}`) and inject only the minimum needed at runtime.
|
|
128
77
|
|
|
129
78
|
### Secret scan
|
|
130
79
|
|
|
131
|
-
This package includes a conservative scanner that flags prompt templates containing strings that strongly resemble real credentials (or private key material).
|
|
132
|
-
|
|
133
|
-
Run:
|
|
134
|
-
|
|
135
80
|
```bash
|
|
136
|
-
|
|
81
|
+
bun run check:secrets
|
|
137
82
|
```
|
|
138
83
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
- `packages/prompts/prompts/**/*.txt`
|
|
142
|
-
- `plugins/**/prompts/**/*.txt`
|
|
84
|
+
Scans `packages/prompts/src/**/*.ts`, plugin prompt TS modules (paths matching `prompts/**/*.ts`, `workflow-prompts/**/*.ts`, etc.), and a few explicit files — see `scripts/check-secrets.js`.
|
package/package.json
CHANGED
|
@@ -1,34 +1,37 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@elizaos/prompts",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "2.0.
|
|
4
|
+
"version": "2.0.11-beta.7",
|
|
5
5
|
"description": "Shared prompt templates for elizaOS across TypeScript, Python, and Rust",
|
|
6
6
|
"type": "module",
|
|
7
|
-
"main": "./
|
|
8
|
-
"types": "./
|
|
7
|
+
"main": "./src/index.ts",
|
|
8
|
+
"types": "./src/index.ts",
|
|
9
9
|
"exports": {
|
|
10
10
|
".": {
|
|
11
|
-
"types": "./
|
|
12
|
-
"import": "./
|
|
11
|
+
"types": "./src/index.ts",
|
|
12
|
+
"import": "./src/index.ts"
|
|
13
13
|
},
|
|
14
|
-
"
|
|
15
|
-
"
|
|
14
|
+
"./*.css": "./dist/*.css",
|
|
15
|
+
"./*": {
|
|
16
|
+
"types": "./dist/*.d.ts",
|
|
17
|
+
"import": "./dist/*.js",
|
|
18
|
+
"default": "./dist/*.js"
|
|
19
|
+
}
|
|
16
20
|
},
|
|
17
21
|
"scripts": {
|
|
18
|
-
"build": "node scripts/generate
|
|
19
|
-
"build:typescript": "node scripts/generate.js --target typescript",
|
|
20
|
-
"build:python": "node scripts/generate.js --target python",
|
|
21
|
-
"build:rust": "node scripts/generate.js --target rust",
|
|
22
|
+
"build": "node scripts/generate-plugin-action-spec.js && bunx @biomejs/biome format --write specs/actions/plugins.generated.json && node scripts/generate-action-docs.js",
|
|
22
23
|
"build:action-docs": "node scripts/generate-action-docs.js",
|
|
23
|
-
"build:plugin-action-spec": "node scripts/generate-plugin-action-spec.js",
|
|
24
|
+
"build:plugin-action-spec": "node scripts/generate-plugin-action-spec.js && bunx @biomejs/biome format --write specs/actions/plugins.generated.json",
|
|
24
25
|
"check:secrets": "node scripts/check-secrets.js",
|
|
25
26
|
"clean": "rm -rf dist",
|
|
26
27
|
"lint": "bunx @biomejs/biome check --write .",
|
|
27
28
|
"lint:check": "bunx @biomejs/biome check .",
|
|
28
|
-
"
|
|
29
|
+
"format:check": "bunx @biomejs/biome format .",
|
|
30
|
+
"typecheck": "echo 'No TypeScript source files to check'",
|
|
31
|
+
"test": "bun test ./test"
|
|
29
32
|
},
|
|
30
33
|
"files": [
|
|
31
|
-
"
|
|
34
|
+
"src/",
|
|
32
35
|
"dist/",
|
|
33
36
|
"scripts/"
|
|
34
37
|
],
|
|
@@ -43,5 +46,5 @@
|
|
|
43
46
|
"publishConfig": {
|
|
44
47
|
"access": "public"
|
|
45
48
|
},
|
|
46
|
-
"gitHead": "
|
|
49
|
+
"gitHead": "cdbc876f793d96073d7eb0d09715a031ce0cd32e"
|
|
47
50
|
}
|
package/scripts/check-secrets.js
CHANGED
|
@@ -1,15 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* Secret/credential scanner for prompt templates.
|
|
4
|
-
*
|
|
5
|
-
* This is intentionally conservative: it only fails on patterns that strongly
|
|
6
|
-
* resemble real credentials (or private key material) to avoid false positives.
|
|
7
|
-
*
|
|
8
|
-
* Scans:
|
|
9
|
-
* - all .txt files under packages/prompts/prompts/
|
|
10
|
-
* - all .txt files under plugin prompt folders (if plugins/ exists)
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
2
|
import fs from "node:fs/promises";
|
|
14
3
|
import path from "node:path";
|
|
15
4
|
import { fileURLToPath } from "node:url";
|
|
@@ -20,47 +9,102 @@ const __dirname = path.dirname(__filename);
|
|
|
20
9
|
const PROMPTS_PKG_DIR = path.resolve(__dirname, "..");
|
|
21
10
|
const REPO_ROOT = path.resolve(PROMPTS_PKG_DIR, "..", "..");
|
|
22
11
|
|
|
23
|
-
const
|
|
24
|
-
|
|
12
|
+
const PROMPT_SCAN_TS_ROOTS = [
|
|
13
|
+
"packages/prompts/src",
|
|
14
|
+
"packages/core/src",
|
|
15
|
+
"plugins",
|
|
16
|
+
];
|
|
17
|
+
|
|
18
|
+
const PROMPT_SCAN_FILES = [
|
|
19
|
+
"packages/core/src/prompts.ts",
|
|
20
|
+
"packages/core/src/services/message.ts",
|
|
21
|
+
"plugins/plugin-music/src/actions/music-player-action-docs.ts",
|
|
22
|
+
];
|
|
23
|
+
|
|
24
|
+
const PROMPT_SCAN_FILE_PATTERNS = [
|
|
25
|
+
/(^|\/)prompts?\.ts$/,
|
|
26
|
+
/(^|\/)prompts\/[^/]+\.ts$/,
|
|
27
|
+
/(^|\/)workflow-prompts\/[^/]+\.ts$/,
|
|
28
|
+
/(^|\/)templates?\.ts$/,
|
|
29
|
+
];
|
|
30
|
+
|
|
31
|
+
const TEST_SOURCE_PATH_PATTERN =
|
|
32
|
+
/(^|\/)(__tests__|tests?|e2e)(\/|$)|\.(test|spec)\.tsx?$/;
|
|
33
|
+
|
|
34
|
+
const SKIP_DIR_NAMES = new Set([
|
|
35
|
+
".git",
|
|
36
|
+
".turbo",
|
|
37
|
+
".next",
|
|
38
|
+
"build",
|
|
39
|
+
"coverage",
|
|
40
|
+
"dist",
|
|
41
|
+
"node_modules",
|
|
42
|
+
"generated",
|
|
43
|
+
]);
|
|
25
44
|
|
|
26
45
|
/**
|
|
27
|
-
* @param {string}
|
|
46
|
+
* @param {string} root
|
|
47
|
+
* @param {(absPath: string, relPath: string) => boolean} predicate
|
|
28
48
|
* @returns {Promise<string[]>}
|
|
29
49
|
*/
|
|
30
|
-
async function
|
|
50
|
+
export async function walkFiles(root, predicate) {
|
|
31
51
|
/** @type {string[]} */
|
|
32
52
|
const out = [];
|
|
33
53
|
|
|
34
54
|
/** @param {string} current */
|
|
35
55
|
async function walk(current) {
|
|
36
|
-
|
|
56
|
+
/** @type {Awaited<ReturnType<typeof fs.readdir>>} */
|
|
57
|
+
let entries;
|
|
58
|
+
try {
|
|
59
|
+
entries = await fs.readdir(current, { withFileTypes: true });
|
|
60
|
+
} catch {
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
37
63
|
for (const entry of entries) {
|
|
38
64
|
const full = path.join(current, entry.name);
|
|
39
65
|
if (entry.isDirectory()) {
|
|
66
|
+
if (SKIP_DIR_NAMES.has(entry.name)) continue;
|
|
40
67
|
await walk(full);
|
|
41
68
|
continue;
|
|
42
69
|
}
|
|
43
|
-
if (entry.isFile()
|
|
44
|
-
|
|
45
|
-
|
|
70
|
+
if (!entry.isFile()) continue;
|
|
71
|
+
const rel = path.relative(REPO_ROOT, full);
|
|
72
|
+
if (predicate(full, rel)) out.push(full);
|
|
46
73
|
}
|
|
47
74
|
}
|
|
48
75
|
|
|
49
|
-
|
|
50
|
-
await walk(dir);
|
|
51
|
-
} catch (_e) {
|
|
52
|
-
// Directory might not exist (e.g., plugins/ in minimal checkouts).
|
|
53
|
-
}
|
|
54
|
-
|
|
76
|
+
await walk(root);
|
|
55
77
|
return out;
|
|
56
78
|
}
|
|
57
79
|
|
|
80
|
+
/**
|
|
81
|
+
* @returns {Promise<string[]>}
|
|
82
|
+
*/
|
|
83
|
+
export async function listPromptTsFiles() {
|
|
84
|
+
/** @type {Set<string>} */
|
|
85
|
+
const set = new Set();
|
|
86
|
+
for (const file of PROMPT_SCAN_FILES) {
|
|
87
|
+
set.add(path.join(REPO_ROOT, file));
|
|
88
|
+
}
|
|
89
|
+
for (const root of PROMPT_SCAN_TS_ROOTS) {
|
|
90
|
+
const absRoot = path.join(REPO_ROOT, root);
|
|
91
|
+
const files = await walkFiles(absRoot, (_abs, rel) => {
|
|
92
|
+
if (!rel.endsWith(".ts") && !rel.endsWith(".tsx")) return false;
|
|
93
|
+
if (TEST_SOURCE_PATH_PATTERN.test(rel)) return false;
|
|
94
|
+
if (/(^|\/)generated\//.test(rel)) return false;
|
|
95
|
+
return PROMPT_SCAN_FILE_PATTERNS.some((p) => p.test(rel));
|
|
96
|
+
});
|
|
97
|
+
for (const f of files) set.add(f);
|
|
98
|
+
}
|
|
99
|
+
return [...set].sort();
|
|
100
|
+
}
|
|
101
|
+
|
|
58
102
|
/**
|
|
59
103
|
* @param {string} filePath
|
|
60
104
|
* @param {string} content
|
|
61
105
|
* @returns {{errors: string[], warnings: string[]}}
|
|
62
106
|
*/
|
|
63
|
-
function scanContent(filePath, content) {
|
|
107
|
+
export function scanContent(filePath, content) {
|
|
64
108
|
/** @type {string[]} */
|
|
65
109
|
const errors = [];
|
|
66
110
|
/** @type {string[]} */
|
|
@@ -115,38 +159,28 @@ function scanContent(filePath, content) {
|
|
|
115
159
|
|
|
116
160
|
for (let i = 0; i < lines.length; i++) {
|
|
117
161
|
const line = lines[i];
|
|
162
|
+
let hasError = false;
|
|
163
|
+
/** @type {string[]} */
|
|
164
|
+
const lineWarnings = [];
|
|
118
165
|
for (const rule of rules) {
|
|
119
166
|
if (rule.re.test(line)) {
|
|
120
167
|
const msg = `${filePath}:${i + 1} ${rule.name}: ${line.trim()}`;
|
|
121
|
-
if (rule.severity === "error")
|
|
122
|
-
|
|
168
|
+
if (rule.severity === "error") {
|
|
169
|
+
errors.push(msg);
|
|
170
|
+
hasError = true;
|
|
171
|
+
} else {
|
|
172
|
+
lineWarnings.push(msg);
|
|
173
|
+
}
|
|
123
174
|
}
|
|
124
175
|
}
|
|
176
|
+
if (!hasError) warnings.push(...lineWarnings);
|
|
125
177
|
}
|
|
126
178
|
|
|
127
179
|
return { errors, warnings };
|
|
128
180
|
}
|
|
129
181
|
|
|
130
182
|
async function main() {
|
|
131
|
-
const
|
|
132
|
-
|
|
133
|
-
/** @type {string[]} */
|
|
134
|
-
let pluginPromptFiles = [];
|
|
135
|
-
try {
|
|
136
|
-
const pluginEntries = await fs.readdir(PLUGINS_DIR, {
|
|
137
|
-
withFileTypes: true,
|
|
138
|
-
});
|
|
139
|
-
for (const entry of pluginEntries) {
|
|
140
|
-
if (!entry.isDirectory()) continue;
|
|
141
|
-
const candidate = path.join(PLUGINS_DIR, entry.name, "prompts");
|
|
142
|
-
const files = await listPromptTxtFiles(candidate);
|
|
143
|
-
pluginPromptFiles = pluginPromptFiles.concat(files);
|
|
144
|
-
}
|
|
145
|
-
} catch {
|
|
146
|
-
// plugins directory missing; ok.
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
const allFiles = [...promptFiles, ...pluginPromptFiles].sort();
|
|
183
|
+
const allFiles = await listPromptTsFiles();
|
|
150
184
|
|
|
151
185
|
/** @type {string[]} */
|
|
152
186
|
const errors = [];
|
|
@@ -154,34 +188,36 @@ async function main() {
|
|
|
154
188
|
const warnings = [];
|
|
155
189
|
|
|
156
190
|
for (const file of allFiles) {
|
|
157
|
-
|
|
191
|
+
let content;
|
|
192
|
+
try {
|
|
193
|
+
content = await fs.readFile(file, "utf-8");
|
|
194
|
+
} catch {
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
158
197
|
const result = scanContent(file, content);
|
|
159
198
|
errors.push(...result.errors);
|
|
160
199
|
warnings.push(...result.warnings);
|
|
161
200
|
}
|
|
162
201
|
|
|
163
202
|
if (warnings.length > 0) {
|
|
164
|
-
// eslint-disable-next-line no-console
|
|
165
203
|
console.warn("\nPrompt secret scan warnings (review recommended):\n");
|
|
166
204
|
for (const w of warnings) {
|
|
167
|
-
// eslint-disable-next-line no-console
|
|
168
205
|
console.warn(`- ${w}`);
|
|
169
206
|
}
|
|
170
207
|
}
|
|
171
208
|
|
|
172
209
|
if (errors.length > 0) {
|
|
173
|
-
// eslint-disable-next-line no-console
|
|
174
210
|
console.error("\nPrompt secret scan errors (must fix):\n");
|
|
175
211
|
for (const e of errors) {
|
|
176
|
-
// eslint-disable-next-line no-console
|
|
177
212
|
console.error(`- ${e}`);
|
|
178
213
|
}
|
|
179
214
|
process.exit(1);
|
|
180
215
|
}
|
|
181
216
|
}
|
|
182
217
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
});
|
|
218
|
+
if (process.argv[1] && path.resolve(process.argv[1]) === __filename) {
|
|
219
|
+
main().catch((err) => {
|
|
220
|
+
console.error(err);
|
|
221
|
+
process.exit(2);
|
|
222
|
+
});
|
|
223
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
|
|
3
|
+
export function readText(filePath) {
|
|
4
|
+
return fs.readFileSync(filePath, "utf-8");
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export function readJson(filePath) {
|
|
8
|
+
return JSON.parse(readText(filePath));
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
export function ensureDirectory(dir) {
|
|
12
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
13
|
+
}
|