pupt-lib 1.2.6 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +292 -256
- package/dist/index.d.ts +458 -29
- package/dist/index.js +2030 -360
- package/dist/jsx-dev-runtime.d.ts +483 -0
- package/dist/jsx-runtime/index.d.ts +2 -29
- package/dist/jsx-runtime/jsx-dev-runtime.d.ts +2 -26
- package/package.json +4 -4
- package/dist/api.d.ts +0 -38
- package/dist/api.d.ts.map +0 -1
- package/dist/component.d.ts +0 -83
- package/dist/component.d.ts.map +0 -1
- package/dist/components/ask/Choice.d.ts +0 -156
- package/dist/components/ask/Choice.d.ts.map +0 -1
- package/dist/components/ask/Confirm.d.ts +0 -62
- package/dist/components/ask/Confirm.d.ts.map +0 -1
- package/dist/components/ask/Date.d.ts +0 -79
- package/dist/components/ask/Date.d.ts.map +0 -1
- package/dist/components/ask/Editor.d.ts +0 -67
- package/dist/components/ask/Editor.d.ts.map +0 -1
- package/dist/components/ask/File.d.ts +0 -85
- package/dist/components/ask/File.d.ts.map +0 -1
- package/dist/components/ask/Label.d.ts +0 -28
- package/dist/components/ask/Label.d.ts.map +0 -1
- package/dist/components/ask/MultiSelect.d.ts +0 -148
- package/dist/components/ask/MultiSelect.d.ts.map +0 -1
- package/dist/components/ask/Number.d.ts +0 -73
- package/dist/components/ask/Number.d.ts.map +0 -1
- package/dist/components/ask/Option.d.ts +0 -29
- package/dist/components/ask/Option.d.ts.map +0 -1
- package/dist/components/ask/Path.d.ts +0 -73
- package/dist/components/ask/Path.d.ts.map +0 -1
- package/dist/components/ask/Rating.d.ts +0 -79
- package/dist/components/ask/Rating.d.ts.map +0 -1
- package/dist/components/ask/ReviewFile.d.ts +0 -79
- package/dist/components/ask/ReviewFile.d.ts.map +0 -1
- package/dist/components/ask/Secret.d.ts +0 -67
- package/dist/components/ask/Secret.d.ts.map +0 -1
- package/dist/components/ask/Select.d.ts +0 -136
- package/dist/components/ask/Select.d.ts.map +0 -1
- package/dist/components/ask/Text.d.ts +0 -67
- package/dist/components/ask/Text.d.ts.map +0 -1
- package/dist/components/ask/index.d.ts +0 -34
- package/dist/components/ask/index.d.ts.map +0 -1
- package/dist/components/ask/utils.d.ts +0 -26
- package/dist/components/ask/utils.d.ts.map +0 -1
- package/dist/components/control/ForEach.d.ts +0 -32
- package/dist/components/control/ForEach.d.ts.map +0 -1
- package/dist/components/control/If.d.ts +0 -24
- package/dist/components/control/If.d.ts.map +0 -1
- package/dist/components/data/Code.d.ts +0 -31
- package/dist/components/data/Code.d.ts.map +0 -1
- package/dist/components/data/Data.d.ts +0 -31
- package/dist/components/data/Data.d.ts.map +0 -1
- package/dist/components/data/File.d.ts +0 -37
- package/dist/components/data/File.d.ts.map +0 -1
- package/dist/components/data/Json.d.ts +0 -25
- package/dist/components/data/Json.d.ts.map +0 -1
- package/dist/components/data/Xml.d.ts +0 -25
- package/dist/components/data/Xml.d.ts.map +0 -1
- package/dist/components/data/index.d.ts +0 -6
- package/dist/components/data/index.d.ts.map +0 -1
- package/dist/components/examples/Example.d.ts +0 -17
- package/dist/components/examples/Example.d.ts.map +0 -1
- package/dist/components/examples/ExampleInput.d.ts +0 -13
- package/dist/components/examples/ExampleInput.d.ts.map +0 -1
- package/dist/components/examples/ExampleOutput.d.ts +0 -13
- package/dist/components/examples/ExampleOutput.d.ts.map +0 -1
- package/dist/components/examples/Examples.d.ts +0 -13
- package/dist/components/examples/Examples.d.ts.map +0 -1
- package/dist/components/examples/index.d.ts +0 -5
- package/dist/components/examples/index.d.ts.map +0 -1
- package/dist/components/index.d.ts +0 -11
- package/dist/components/index.d.ts.map +0 -1
- package/dist/components/meta/Uses.d.ts +0 -98
- package/dist/components/meta/Uses.d.ts.map +0 -1
- package/dist/components/meta/index.d.ts +0 -2
- package/dist/components/meta/index.d.ts.map +0 -1
- package/dist/components/post-execution/OpenUrl.d.ts +0 -29
- package/dist/components/post-execution/OpenUrl.d.ts.map +0 -1
- package/dist/components/post-execution/PostExecution.d.ts +0 -13
- package/dist/components/post-execution/PostExecution.d.ts.map +0 -1
- package/dist/components/post-execution/ReviewFile.d.ts +0 -29
- package/dist/components/post-execution/ReviewFile.d.ts.map +0 -1
- package/dist/components/post-execution/RunCommand.d.ts +0 -35
- package/dist/components/post-execution/RunCommand.d.ts.map +0 -1
- package/dist/components/post-execution/index.d.ts +0 -5
- package/dist/components/post-execution/index.d.ts.map +0 -1
- package/dist/components/reasoning/Step.d.ts +0 -25
- package/dist/components/reasoning/Step.d.ts.map +0 -1
- package/dist/components/reasoning/Steps.d.ts +0 -14
- package/dist/components/reasoning/Steps.d.ts.map +0 -1
- package/dist/components/reasoning/index.d.ts +0 -3
- package/dist/components/reasoning/index.d.ts.map +0 -1
- package/dist/components/structural/Audience.d.ts +0 -25
- package/dist/components/structural/Audience.d.ts.map +0 -1
- package/dist/components/structural/Constraint.d.ts +0 -31
- package/dist/components/structural/Constraint.d.ts.map +0 -1
- package/dist/components/structural/Context.d.ts +0 -25
- package/dist/components/structural/Context.d.ts.map +0 -1
- package/dist/components/structural/Criterion.d.ts +0 -13
- package/dist/components/structural/Criterion.d.ts.map +0 -1
- package/dist/components/structural/Format.d.ts +0 -37
- package/dist/components/structural/Format.d.ts.map +0 -1
- package/dist/components/structural/Prompt.d.ts +0 -43
- package/dist/components/structural/Prompt.d.ts.map +0 -1
- package/dist/components/structural/Role.d.ts +0 -37
- package/dist/components/structural/Role.d.ts.map +0 -1
- package/dist/components/structural/Section.d.ts +0 -31
- package/dist/components/structural/Section.d.ts.map +0 -1
- package/dist/components/structural/SuccessCriteria.d.ts +0 -25
- package/dist/components/structural/SuccessCriteria.d.ts.map +0 -1
- package/dist/components/structural/Task.d.ts +0 -25
- package/dist/components/structural/Task.d.ts.map +0 -1
- package/dist/components/structural/Tone.d.ts +0 -25
- package/dist/components/structural/Tone.d.ts.map +0 -1
- package/dist/components/structural/index.d.ts +0 -12
- package/dist/components/structural/index.d.ts.map +0 -1
- package/dist/components/utility/Cwd.d.ts +0 -11
- package/dist/components/utility/Cwd.d.ts.map +0 -1
- package/dist/components/utility/DateTime.d.ts +0 -23
- package/dist/components/utility/DateTime.d.ts.map +0 -1
- package/dist/components/utility/Hostname.d.ts +0 -11
- package/dist/components/utility/Hostname.d.ts.map +0 -1
- package/dist/components/utility/Timestamp.d.ts +0 -11
- package/dist/components/utility/Timestamp.d.ts.map +0 -1
- package/dist/components/utility/UUID.d.ts +0 -11
- package/dist/components/utility/UUID.d.ts.map +0 -1
- package/dist/components/utility/Username.d.ts +0 -11
- package/dist/components/utility/Username.d.ts.map +0 -1
- package/dist/components/utility/index.d.ts +0 -7
- package/dist/components/utility/index.d.ts.map +0 -1
- package/dist/create-prompt.d.ts +0 -118
- package/dist/create-prompt.d.ts.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/jsx-runtime/index.d.ts.map +0 -1
- package/dist/jsx-runtime/jsx-dev-runtime.d.ts.map +0 -1
- package/dist/render.d.ts +0 -19
- package/dist/render.d.ts.map +0 -1
- package/dist/services/babel-plugins/index.d.ts +0 -3
- package/dist/services/babel-plugins/index.d.ts.map +0 -1
- package/dist/services/babel-plugins/name-hoisting.d.ts +0 -8
- package/dist/services/babel-plugins/name-hoisting.d.ts.map +0 -1
- package/dist/services/babel-plugins/uses-to-import.d.ts +0 -16
- package/dist/services/babel-plugins/uses-to-import.d.ts.map +0 -1
- package/dist/services/browser-support.d.ts +0 -185
- package/dist/services/browser-support.d.ts.map +0 -1
- package/dist/services/file-search-engine.d.ts +0 -162
- package/dist/services/file-search-engine.d.ts.map +0 -1
- package/dist/services/formula-parser.d.ts +0 -9
- package/dist/services/formula-parser.d.ts.map +0 -1
- package/dist/services/input-iterator.d.ts +0 -54
- package/dist/services/input-iterator.d.ts.map +0 -1
- package/dist/services/module-evaluator.d.ts +0 -38
- package/dist/services/module-evaluator.d.ts.map +0 -1
- package/dist/services/module-loader.d.ts +0 -92
- package/dist/services/module-loader.d.ts.map +0 -1
- package/dist/services/preprocessor.d.ts +0 -52
- package/dist/services/preprocessor.d.ts.map +0 -1
- package/dist/services/prop-validator.d.ts +0 -21
- package/dist/services/prop-validator.d.ts.map +0 -1
- package/dist/services/search-engine.d.ts +0 -10
- package/dist/services/search-engine.d.ts.map +0 -1
- package/dist/services/transformer.d.ts +0 -38
- package/dist/services/transformer.d.ts.map +0 -1
- package/dist/types/component.d.ts +0 -30
- package/dist/types/component.d.ts.map +0 -1
- package/dist/types/context.d.ts +0 -341
- package/dist/types/context.d.ts.map +0 -1
- package/dist/types/element.d.ts +0 -47
- package/dist/types/element.d.ts.map +0 -1
- package/dist/types/index.d.ts +0 -11
- package/dist/types/index.d.ts.map +0 -1
- package/dist/types/input.d.ts +0 -61
- package/dist/types/input.d.ts.map +0 -1
- package/dist/types/module.d.ts +0 -61
- package/dist/types/module.d.ts.map +0 -1
- package/dist/types/render.d.ts +0 -92
- package/dist/types/render.d.ts.map +0 -1
- package/dist/types/search.d.ts +0 -59
- package/dist/types/search.d.ts.map +0 -1
- package/dist/types/symbols.d.ts +0 -9
- package/dist/types/symbols.d.ts.map +0 -1
package/README.md
CHANGED
|
@@ -8,14 +8,15 @@ A TypeScript library for creating AI prompts as versionable, composable, shareab
|
|
|
8
8
|
|
|
9
9
|
**Features:**
|
|
10
10
|
|
|
11
|
-
- **JSX Syntax**
|
|
12
|
-
- **
|
|
13
|
-
- **
|
|
14
|
-
- **
|
|
15
|
-
- **
|
|
16
|
-
- **
|
|
17
|
-
- **
|
|
18
|
-
- **
|
|
11
|
+
- **JSX Syntax** — Write prompts using familiar JSX/TSX syntax with 50+ built-in components
|
|
12
|
+
- **`.prompt` Files** — Simplified format with no imports, no exports — just JSX
|
|
13
|
+
- **Composable** — Build complex prompts from reusable, shareable components
|
|
14
|
+
- **Provider Targeting** — Adapt output for Claude, GPT, Gemini, and others via environment config
|
|
15
|
+
- **Presets** — Role, task, constraint, and steps presets encode prompt engineering best practices
|
|
16
|
+
- **Smart Defaults** — Auto-generated role, format, and constraint sections with full opt-out control
|
|
17
|
+
- **Version Controlled** — Prompts live in files, tracked in git, reviewed in PRs
|
|
18
|
+
- **Shareable** — Publish prompt libraries to npm, consume others' work via npm, URLs, or local files
|
|
19
|
+
- **Browser & Node.js** — Works in both environments with runtime JSX transformation
|
|
19
20
|
|
|
20
21
|
## Installation
|
|
21
22
|
|
|
@@ -29,11 +30,44 @@ For build-time JSX transformation (recommended for production), also install the
|
|
|
29
30
|
npm install --save-dev @babel/core @babel/plugin-transform-react-jsx @babel/preset-typescript
|
|
30
31
|
```
|
|
31
32
|
|
|
32
|
-
## Quick Start
|
|
33
|
+
## Quick Start with `.prompt`
|
|
33
34
|
|
|
34
|
-
|
|
35
|
+
The simplest way to write a prompt — no imports or exports needed:
|
|
36
|
+
|
|
37
|
+
```xml
|
|
38
|
+
<!-- greeting.prompt -->
|
|
39
|
+
<Prompt name="greeting" description="A friendly greeting prompt">
|
|
40
|
+
<Role>You are a friendly assistant.</Role>
|
|
41
|
+
<Task>
|
|
42
|
+
Greet the user named <Ask.Text name="userName" label="User's name" /> warmly.
|
|
43
|
+
</Task>
|
|
44
|
+
<Constraint type="must">Keep the greeting under 50 words.</Constraint>
|
|
45
|
+
</Prompt>
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Load and render it:
|
|
49
|
+
|
|
50
|
+
```typescript
|
|
51
|
+
import { createPromptFromSource, render } from 'pupt-lib';
|
|
52
|
+
import { readFile } from 'fs/promises';
|
|
53
|
+
|
|
54
|
+
const source = await readFile('./greeting.prompt', 'utf-8');
|
|
55
|
+
const element = await createPromptFromSource(source, 'greeting.prompt');
|
|
56
|
+
const result = await render(element, {
|
|
57
|
+
inputs: { userName: 'Alice' },
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
console.log(result.text);
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Quick Start with `.tsx`
|
|
64
|
+
|
|
65
|
+
The same prompt as a TypeScript JSX file — explicit imports, full type safety:
|
|
35
66
|
|
|
36
67
|
```tsx
|
|
68
|
+
// greeting.tsx
|
|
69
|
+
import { Prompt, Role, Task, Constraint, Ask } from 'pupt-lib';
|
|
70
|
+
|
|
37
71
|
export default (
|
|
38
72
|
<Prompt name="greeting" description="A friendly greeting prompt">
|
|
39
73
|
<Role>You are a friendly assistant.</Role>
|
|
@@ -45,318 +79,317 @@ export default (
|
|
|
45
79
|
);
|
|
46
80
|
```
|
|
47
81
|
|
|
48
|
-
|
|
82
|
+
Load with `createPrompt` (reads the file for you):
|
|
49
83
|
|
|
50
84
|
```typescript
|
|
51
|
-
import { createPrompt, render
|
|
85
|
+
import { createPrompt, render } from 'pupt-lib';
|
|
52
86
|
|
|
53
|
-
// Load the prompt
|
|
54
87
|
const element = await createPrompt('./greeting.tsx');
|
|
88
|
+
const result = await render(element, {
|
|
89
|
+
inputs: { userName: 'Alice' },
|
|
90
|
+
});
|
|
91
|
+
|
|
92
|
+
console.log(result.text);
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
## Collecting User Inputs
|
|
96
|
+
|
|
97
|
+
When prompts contain `<Ask.*>` components, use `createInputIterator` to collect values interactively:
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
import { createPrompt, createInputIterator, render } from 'pupt-lib';
|
|
55
101
|
|
|
56
|
-
|
|
102
|
+
const element = await createPrompt('./my-prompt.tsx');
|
|
57
103
|
const iterator = createInputIterator(element);
|
|
58
|
-
|
|
104
|
+
|
|
105
|
+
// Start iteration
|
|
106
|
+
await iterator.start();
|
|
107
|
+
|
|
108
|
+
// Loop through each input requirement
|
|
59
109
|
while (!iterator.isDone()) {
|
|
60
110
|
const req = iterator.current();
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
111
|
+
console.log(`${req.label} (${req.type}, required: ${req.required})`);
|
|
112
|
+
|
|
113
|
+
const answer = await askUser(req); // your UI logic
|
|
114
|
+
const validation = await iterator.submit(answer);
|
|
115
|
+
|
|
116
|
+
if (!validation.valid) {
|
|
117
|
+
console.log('Errors:', validation.errors.map(e => e.message));
|
|
118
|
+
continue; // re-prompt for same input
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
await iterator.advance();
|
|
64
122
|
}
|
|
65
123
|
|
|
66
|
-
// Render
|
|
67
|
-
const result = render(element, { inputs: iterator.getValues() });
|
|
68
|
-
console.log(result.text);
|
|
124
|
+
// Render with collected values
|
|
125
|
+
const result = await render(element, { inputs: iterator.getValues() });
|
|
69
126
|
```
|
|
70
127
|
|
|
71
|
-
Or
|
|
128
|
+
Or use non-interactive mode to auto-fill defaults:
|
|
72
129
|
|
|
73
130
|
```typescript
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
const
|
|
77
|
-
const result = render(element, {
|
|
78
|
-
inputs: { userName: 'Alice' }
|
|
79
|
-
});
|
|
80
|
-
console.log(result.text);
|
|
131
|
+
const iterator = createInputIterator(element, { nonInteractive: true });
|
|
132
|
+
const values = await iterator.runNonInteractive();
|
|
133
|
+
const result = await render(element, { inputs: values });
|
|
81
134
|
```
|
|
82
135
|
|
|
83
|
-
##
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
| Component | Description |
|
|
88
|
-
|-----------|-------------|
|
|
89
|
-
| `<Prompt>` | Root container for a complete prompt. Props: `name`, `description`, `tags`, `version` |
|
|
90
|
-
| `<Section>` | Creates a labeled section with optional XML delimiters |
|
|
91
|
-
| `<Role>` | Defines the AI persona/role. Props: `expertise`, `domain` |
|
|
92
|
-
| `<Task>` | Clearly states what the AI should do |
|
|
93
|
-
| `<Context>` | Provides background information |
|
|
94
|
-
| `<Constraint>` | Adds boundaries/rules. Props: `type` (`must`, `should`, `must-not`) |
|
|
95
|
-
| `<Format>` | Specifies output format. Props: `type` (`json`, `markdown`, `code`, `list`), `schema` |
|
|
96
|
-
| `<Audience>` | Who the output is for. Props: `expertise`, `domain` |
|
|
97
|
-
| `<Tone>` | Emotional quality of output. Props: `type`, `formality` |
|
|
98
|
-
| `<SuccessCriteria>` | Container for success criteria |
|
|
99
|
-
| `<Criterion>` | Individual success criterion. Props: `priority` |
|
|
100
|
-
|
|
101
|
-
### Example Components
|
|
102
|
-
|
|
103
|
-
| Component | Description |
|
|
104
|
-
|-----------|-------------|
|
|
105
|
-
| `<Examples>` | Container for multiple examples |
|
|
106
|
-
| `<Example>` | Single example with input/output |
|
|
107
|
-
| `<ExampleInput>` | Input portion of an example |
|
|
108
|
-
| `<ExampleOutput>` | Expected output of an example |
|
|
109
|
-
|
|
110
|
-
### Reasoning Components
|
|
111
|
-
|
|
112
|
-
| Component | Description |
|
|
113
|
-
|-----------|-------------|
|
|
114
|
-
| `<Steps>` | Encourages step-by-step thinking |
|
|
115
|
-
| `<Step>` | Individual step in a reasoning chain. Props: `number` |
|
|
116
|
-
|
|
117
|
-
### Data Components
|
|
118
|
-
|
|
119
|
-
| Component | Description |
|
|
120
|
-
|-----------|-------------|
|
|
121
|
-
| `<Data>` | Embeds data with optional formatting. Props: `name`, `format` |
|
|
122
|
-
| `<Code>` | Embeds code with language hint. Props: `language`, `filename` |
|
|
123
|
-
| `<File>` | Embeds file contents. Props: `path` |
|
|
124
|
-
| `<Json>` | Embeds JSON data. Props: `name` |
|
|
125
|
-
| `<Xml>` | Embeds XML data. Props: `name` |
|
|
126
|
-
|
|
127
|
-
### Utility Components
|
|
128
|
-
|
|
129
|
-
| Component | Description |
|
|
130
|
-
|-----------|-------------|
|
|
131
|
-
| `<UUID>` | Generates a unique identifier |
|
|
132
|
-
| `<Timestamp>` | Current Unix timestamp |
|
|
133
|
-
| `<DateTime>` | Current date/time. Props: `format` |
|
|
134
|
-
| `<Hostname>` | Current machine hostname |
|
|
135
|
-
| `<Username>` | Current system username |
|
|
136
|
-
| `<Cwd>` | Current working directory |
|
|
137
|
-
|
|
138
|
-
### Control Flow Components
|
|
139
|
-
|
|
140
|
-
| Component | Description |
|
|
141
|
-
|-----------|-------------|
|
|
142
|
-
| `<If>` | Conditional rendering. Props: `when` (Excel formula or JS expression) |
|
|
143
|
-
| `<ForEach>` | Loop over items. Props: `items`, `as` |
|
|
144
|
-
| `<Scope>` | Resolve components from a specific library. Props: `from` |
|
|
145
|
-
|
|
146
|
-
### User Input Components (Ask.*)
|
|
147
|
-
|
|
148
|
-
| Component | Description |
|
|
149
|
-
|-----------|-------------|
|
|
150
|
-
| `<Ask.Text>` | Single-line text input. Props: `name`, `label`, `required`, `default`, `pattern` |
|
|
151
|
-
| `<Ask.Editor>` | Multi-line text editor. Props: `name`, `label`, `language` |
|
|
152
|
-
| `<Ask.Select>` | Single choice from options. Props: `name`, `label`, `options` or `<Option>` children |
|
|
153
|
-
| `<Ask.MultiSelect>` | Multiple choices. Props: `name`, `label`, `options` or `<Option>` children |
|
|
154
|
-
| `<Ask.Confirm>` | Yes/no question. Props: `name`, `label`, `default` |
|
|
155
|
-
| `<Ask.Choice>` | Binary choice with custom labels. Props: `name`, `label`, `options` |
|
|
156
|
-
| `<Ask.Number>` | Numeric input. Props: `name`, `label`, `min`, `max`, `default` |
|
|
157
|
-
| `<Ask.File>` | File path input. Props: `name`, `label`, `mustExist` |
|
|
158
|
-
| `<Ask.Path>` | Directory path input. Props: `name`, `label`, `mustBeDirectory` |
|
|
159
|
-
| `<Ask.Date>` | Date selection. Props: `name`, `label` |
|
|
160
|
-
| `<Ask.Secret>` | Masked input for sensitive values. Props: `name`, `label`, `validator` |
|
|
161
|
-
| `<Ask.Rating>` | Numeric scale input. Props: `name`, `label`, `min`, `max`, `labels` or `<Label>` children |
|
|
162
|
-
| `<Ask.ReviewFile>` | File input with post-execution review. Props: `name`, `label` |
|
|
163
|
-
| `<Option>` | Option for Select/MultiSelect. Props: `value`, `label`, children (render text) |
|
|
164
|
-
| `<Label>` | Label for Rating scale. Props: `value`, children (label text) |
|
|
165
|
-
|
|
166
|
-
### Meta Components
|
|
167
|
-
|
|
168
|
-
| Component | Description |
|
|
169
|
-
|-----------|-------------|
|
|
170
|
-
| `<Uses>` | Declares module dependencies. Props: `src`, `optional` |
|
|
171
|
-
|
|
172
|
-
### Post-Execution Components
|
|
173
|
-
|
|
174
|
-
| Component | Description |
|
|
175
|
-
|-----------|-------------|
|
|
176
|
-
| `<PostExecution>` | Container for post-execution actions |
|
|
177
|
-
| `<ReviewFile>` | Open a file for review after prompt execution. Props: `file`, `editor` |
|
|
178
|
-
| `<OpenUrl>` | Open a URL in browser. Props: `url`, `browser` |
|
|
179
|
-
| `<RunCommand>` | Execute a shell command. Props: `command`, `cwd` |
|
|
180
|
-
|
|
181
|
-
## API Summary
|
|
182
|
-
|
|
183
|
-
| Export | Type | Description |
|
|
184
|
-
|--------|------|-------------|
|
|
185
|
-
| `render(element, options?)` | Function | Render a PuptElement tree to text |
|
|
186
|
-
| `createPrompt(filePath)` | Function | Create a prompt from a JSX/TSX file |
|
|
187
|
-
| `createPromptFromSource(source, filename)` | Function | Create a prompt from source string |
|
|
188
|
-
| `createInputIterator(element)` | Function | Create iterator for collecting user inputs |
|
|
189
|
-
| `Component<Props>` | Class | Base class for custom components |
|
|
190
|
-
| `Pupt` | Class | High-level API for loading and managing prompt libraries |
|
|
191
|
-
| `createSearchEngine(config?)` | Function | Create fuzzy search engine for prompts |
|
|
192
|
-
| `createRegistry()` | Function | Create a new component registry |
|
|
193
|
-
| `defaultRegistry` | Const | The default global component registry |
|
|
194
|
-
|
|
195
|
-
## Detailed API Usage
|
|
196
|
-
|
|
197
|
-
### Rendering Prompts
|
|
136
|
+
## Working with Results
|
|
137
|
+
|
|
138
|
+
`render()` returns a `RenderResult` discriminated union:
|
|
198
139
|
|
|
199
140
|
```typescript
|
|
200
|
-
|
|
141
|
+
const result = await render(element, { inputs: { userName: 'Alice' } });
|
|
201
142
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
143
|
+
if (result.ok) {
|
|
144
|
+
console.log(result.text); // The rendered prompt string
|
|
145
|
+
console.log(result.postExecution); // Post-execution actions (if any)
|
|
146
|
+
if (result.errors) {
|
|
147
|
+
console.log('Warnings:', result.errors); // Non-fatal validation warnings
|
|
148
|
+
}
|
|
149
|
+
} else {
|
|
150
|
+
console.log('Errors:', result.errors); // Validation/runtime errors
|
|
151
|
+
console.log(result.text); // Best-effort partial output
|
|
152
|
+
}
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## `.prompt` vs `.tsx`
|
|
156
|
+
|
|
157
|
+
| Feature | `.prompt` | `.tsx` |
|
|
158
|
+
|---------|-----------|--------|
|
|
159
|
+
| Imports | Auto-injected for all built-in components | Explicit `import` statements |
|
|
160
|
+
| Exports | Auto-wrapped with `export default` | Explicit `export default` |
|
|
161
|
+
| Custom components | Via `<Uses>` declarations | Standard `import` |
|
|
162
|
+
| Component definitions | Not supported | Define components in same file |
|
|
163
|
+
| Target audience | Non-technical users, simple prompts | Developers, complex prompts |
|
|
164
|
+
| Behavior | Identical after preprocessing | Identical after preprocessing |
|
|
165
|
+
|
|
166
|
+
Both formats go through the same transformation pipeline and produce identical output.
|
|
167
|
+
|
|
168
|
+
## Component Overview
|
|
169
|
+
|
|
170
|
+
pupt-lib includes 50+ built-in components organized by category:
|
|
171
|
+
|
|
172
|
+
| Category | Count | Key Components |
|
|
173
|
+
|----------|-------|----------------|
|
|
174
|
+
| **Structural** | 24 | `Prompt`, `Role`, `Task`, `Context`, `Constraint`, `Format`, `Audience`, `Tone` |
|
|
175
|
+
| **Ask (User Input)** | 15 | `Ask.Text`, `Ask.Number`, `Ask.Select`, `Ask.Confirm`, `Ask.MultiSelect` |
|
|
176
|
+
| **Data** | 5 | `Code`, `Data`, `File`, `Json`, `Xml` |
|
|
177
|
+
| **Examples** | 5 | `Examples`, `Example`, `ExampleInput`, `ExampleOutput`, `NegativeExample` |
|
|
178
|
+
| **Reasoning** | 3 | `Steps`, `Step`, `ChainOfThought` |
|
|
179
|
+
| **Control Flow** | 2 | `If`, `ForEach` |
|
|
180
|
+
| **Post-Execution** | 4 | `PostExecution`, `ReviewFile`, `OpenUrl`, `RunCommand` |
|
|
181
|
+
| **Utility** | 6 | `UUID`, `Timestamp`, `DateTime`, `Hostname`, `Username`, `Cwd` |
|
|
182
|
+
| **Meta** | 1 | `Uses` |
|
|
209
183
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
184
|
+
See [docs/COMPONENTS.md](docs/COMPONENTS.md) for the full reference with all props.
|
|
185
|
+
|
|
186
|
+
## Environment & Providers
|
|
187
|
+
|
|
188
|
+
Components adapt their output based on the target LLM provider. Set the provider via the `env` option:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
import { render, createEnvironment } from 'pupt-lib';
|
|
192
|
+
|
|
193
|
+
// Target Anthropic Claude
|
|
194
|
+
const result = await render(element, {
|
|
195
|
+
inputs: { ... },
|
|
196
|
+
env: createEnvironment({
|
|
197
|
+
llm: { provider: 'anthropic' },
|
|
198
|
+
}),
|
|
214
199
|
});
|
|
215
200
|
|
|
216
|
-
|
|
217
|
-
|
|
201
|
+
// Target OpenAI GPT (uses markdown delimiters instead of XML)
|
|
202
|
+
const result2 = await render(element, {
|
|
203
|
+
inputs: { ... },
|
|
204
|
+
env: createEnvironment({
|
|
205
|
+
llm: { provider: 'openai' },
|
|
206
|
+
}),
|
|
207
|
+
});
|
|
218
208
|
```
|
|
219
209
|
|
|
220
|
-
|
|
210
|
+
Supported providers: `anthropic`, `openai`, `google`, `meta`, `mistral`, `deepseek`, `xai`, `cohere`. Provider can also be auto-inferred from model name:
|
|
221
211
|
|
|
222
212
|
```typescript
|
|
223
|
-
|
|
213
|
+
env: createEnvironment({
|
|
214
|
+
llm: { model: 'claude-sonnet-4-5-20250929' }, // auto-infers provider: 'anthropic'
|
|
215
|
+
})
|
|
216
|
+
```
|
|
224
217
|
|
|
225
|
-
|
|
226
|
-
const iterator = createInputIterator(element);
|
|
218
|
+
Each provider has adaptations for role prefix style, constraint framing, format preference, and instruction style.
|
|
227
219
|
|
|
228
|
-
|
|
229
|
-
iterator.start();
|
|
220
|
+
## Presets
|
|
230
221
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
222
|
+
Many components accept a `preset` prop that loads pre-configured settings:
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
<Role preset="engineer" />
|
|
226
|
+
// Renders: "You are a senior Software Engineer with expertise in software development, programming, system design."
|
|
234
227
|
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
console.log(`Label: ${req.label}`);
|
|
238
|
-
console.log(`Required: ${req.required}`);
|
|
228
|
+
<Steps preset="debugging" />
|
|
229
|
+
// Renders step-by-step phases: Reproduce → Isolate → Fix → Verify
|
|
239
230
|
|
|
240
|
-
|
|
241
|
-
|
|
231
|
+
<Constraint preset="cite-sources" />
|
|
232
|
+
// Renders: "Cite sources for factual claims" with type "must"
|
|
233
|
+
```
|
|
242
234
|
|
|
243
|
-
|
|
244
|
-
const result = await iterator.submit(answer);
|
|
245
|
-
if (!result.valid) {
|
|
246
|
-
console.log(`Validation error: ${result.errors.map(e => e.message).join(', ')}`);
|
|
247
|
-
continue; // Re-prompt for same input
|
|
248
|
-
}
|
|
235
|
+
Available preset categories:
|
|
249
236
|
|
|
250
|
-
|
|
251
|
-
|
|
237
|
+
| Preset | Keys | Used by |
|
|
238
|
+
|--------|------|---------|
|
|
239
|
+
| **Role** | `assistant`, `engineer`, `writer`, `analyst`, `teacher`, +25 more | `<Role>` |
|
|
240
|
+
| **Task** | `summarize`, `code-review`, `translate`, `explain`, `generate-code`, +5 more | `<Task>` |
|
|
241
|
+
| **Constraint** | `be-concise`, `cite-sources`, `no-opinions`, `no-hallucination`, +4 more | `<Constraint>` |
|
|
242
|
+
| **Steps** | `analysis`, `problem-solving`, `code-generation`, `debugging`, `research` | `<Steps>` |
|
|
243
|
+
| **Guardrails** | `standard`, `strict`, `minimal` | `<Guardrails>` |
|
|
252
244
|
|
|
253
|
-
|
|
254
|
-
|
|
245
|
+
See [docs/COMPONENTS.md](docs/COMPONENTS.md) for the full list of preset keys.
|
|
246
|
+
|
|
247
|
+
## Prompt Defaults
|
|
248
|
+
|
|
249
|
+
`<Prompt>` auto-generates Role, Format, and Constraint sections when you don't provide them. This means a minimal prompt:
|
|
250
|
+
|
|
251
|
+
```xml
|
|
252
|
+
<Prompt name="helper">
|
|
253
|
+
<Task>Help the user with their question.</Task>
|
|
254
|
+
</Prompt>
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
...automatically includes a default role ("You are a helpful Assistant"), format guidance, and basic constraints.
|
|
258
|
+
|
|
259
|
+
**Controlling defaults:**
|
|
260
|
+
|
|
261
|
+
```tsx
|
|
262
|
+
// Disable all defaults
|
|
263
|
+
<Prompt name="bare-prompt" bare>
|
|
264
|
+
<Task>Just the task, nothing else.</Task>
|
|
265
|
+
</Prompt>
|
|
266
|
+
|
|
267
|
+
// Disable specific defaults
|
|
268
|
+
<Prompt name="custom" noRole noFormat>
|
|
269
|
+
<Task>Only constraints are auto-generated.</Task>
|
|
270
|
+
</Prompt>
|
|
271
|
+
|
|
272
|
+
// Fine-grained control
|
|
273
|
+
<Prompt name="custom" defaults={{ role: true, format: false, constraints: true }}>
|
|
274
|
+
<Task>Role and constraints, but no format section.</Task>
|
|
275
|
+
</Prompt>
|
|
276
|
+
|
|
277
|
+
// Shorthand: customize the default role
|
|
278
|
+
<Prompt name="expert" role="engineer" expertise="TypeScript">
|
|
279
|
+
<Task>Review this code.</Task>
|
|
280
|
+
</Prompt>
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Slots** let you replace default sections with custom components:
|
|
284
|
+
|
|
285
|
+
```tsx
|
|
286
|
+
<Prompt name="custom" slots={{ role: MyCustomRole }}>
|
|
287
|
+
<Task>Uses MyCustomRole instead of the default role.</Task>
|
|
288
|
+
</Prompt>
|
|
255
289
|
```
|
|
256
290
|
|
|
257
|
-
|
|
291
|
+
## Creating Custom Components
|
|
292
|
+
|
|
293
|
+
Extend `Component` and implement `render(props, resolvedValue, context)`:
|
|
258
294
|
|
|
259
295
|
```typescript
|
|
260
|
-
import { Component
|
|
296
|
+
import { Component } from 'pupt-lib';
|
|
297
|
+
import type { PuptNode, RenderContext } from 'pupt-lib';
|
|
298
|
+
import { z } from 'zod';
|
|
261
299
|
|
|
262
|
-
|
|
263
|
-
level: 'info'
|
|
264
|
-
|
|
265
|
-
|
|
300
|
+
const warningSchema = z.object({
|
|
301
|
+
level: z.enum(['info', 'warning', 'error']),
|
|
302
|
+
});
|
|
303
|
+
|
|
304
|
+
type WarningProps = z.infer<typeof warningSchema> & { children?: PuptNode };
|
|
266
305
|
|
|
267
306
|
class Warning extends Component<WarningProps> {
|
|
268
|
-
|
|
307
|
+
static schema = warningSchema;
|
|
308
|
+
|
|
309
|
+
render(props: WarningProps, _resolvedValue: void, context: RenderContext): PuptNode {
|
|
269
310
|
const prefix = {
|
|
270
311
|
info: 'INFO',
|
|
271
312
|
warning: 'WARNING',
|
|
272
|
-
error: 'ERROR'
|
|
313
|
+
error: 'ERROR',
|
|
273
314
|
}[props.level];
|
|
274
315
|
|
|
275
316
|
return `[${prefix}] ${props.children}`;
|
|
276
317
|
}
|
|
277
318
|
}
|
|
278
|
-
|
|
279
|
-
// Register with the default registry
|
|
280
|
-
import { defaultRegistry } from 'pupt-lib';
|
|
281
|
-
defaultRegistry.register('Warning', Warning);
|
|
282
319
|
```
|
|
283
320
|
|
|
284
|
-
|
|
321
|
+
Use in `.prompt` files with `<Uses>`:
|
|
285
322
|
|
|
286
|
-
```
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
// Initialize with module sources
|
|
290
|
-
const pupt = new Pupt({
|
|
291
|
-
modules: [
|
|
292
|
-
'@acme/prompts', // npm package
|
|
293
|
-
'https://example.com/prompts.js', // URL
|
|
294
|
-
'./local-prompts/', // local path
|
|
295
|
-
],
|
|
296
|
-
});
|
|
323
|
+
```xml
|
|
324
|
+
<Uses component="Warning" from="./my-components" />
|
|
297
325
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
console.log(prompts.map(p => p.name));
|
|
303
|
-
|
|
304
|
-
// Filter by tags
|
|
305
|
-
const devPrompts = pupt.getPrompts({ tags: ['development'] });
|
|
326
|
+
<Prompt name="example">
|
|
327
|
+
<Warning level="info">This is a custom component.</Warning>
|
|
328
|
+
</Prompt>
|
|
329
|
+
```
|
|
306
330
|
|
|
307
|
-
|
|
308
|
-
|
|
331
|
+
The `Component` base class provides helpers:
|
|
332
|
+
- `getProvider(context)` — Get the current LLM provider
|
|
333
|
+
- `getDelimiter(context)` — Get the delimiter style (`xml`, `markdown`, or `none`)
|
|
334
|
+
- `hasContent(children)` — Check if children have meaningful content
|
|
309
335
|
|
|
310
|
-
|
|
311
|
-
const prompt = pupt.getPrompt('security-review');
|
|
312
|
-
if (prompt) {
|
|
313
|
-
const result = prompt.render({ inputs: { code: sourceCode } });
|
|
314
|
-
console.log(result.text);
|
|
315
|
-
}
|
|
336
|
+
## Advanced Features
|
|
316
337
|
|
|
317
|
-
|
|
318
|
-
const tags = pupt.getTags();
|
|
319
|
-
```
|
|
338
|
+
**Conditional rendering** with `<If>`:
|
|
320
339
|
|
|
321
|
-
|
|
340
|
+
```tsx
|
|
341
|
+
// Boolean condition
|
|
342
|
+
<If when={isAdmin}>
|
|
343
|
+
<Task>Perform admin operations.</Task>
|
|
344
|
+
</If>
|
|
322
345
|
|
|
323
|
-
|
|
324
|
-
// Excel formula syntax (accessible to non-technical users)
|
|
346
|
+
// Excel-style formula (evaluated against input values)
|
|
325
347
|
<If when='=AND(count>5, userType="admin")'>
|
|
326
348
|
<Ask.Text name="adminCode" label="Admin authorization code" />
|
|
327
349
|
</If>
|
|
328
350
|
|
|
329
|
-
//
|
|
330
|
-
<If
|
|
331
|
-
<
|
|
351
|
+
// Provider-specific content
|
|
352
|
+
<If provider="anthropic">
|
|
353
|
+
<Context>Use XML tags for structured output.</Context>
|
|
354
|
+
</If>
|
|
355
|
+
<If notProvider="anthropic">
|
|
356
|
+
<Context>Use markdown headers for structured output.</Context>
|
|
332
357
|
</If>
|
|
333
358
|
```
|
|
334
359
|
|
|
335
|
-
|
|
360
|
+
**Iteration** with `<ForEach>`:
|
|
336
361
|
|
|
337
|
-
```
|
|
338
|
-
|
|
362
|
+
```tsx
|
|
363
|
+
<ForEach items={['bug fix', 'feature', 'refactor']} as="type">
|
|
364
|
+
<Step>Handle the {type} case.</Step>
|
|
365
|
+
</ForEach>
|
|
366
|
+
```
|
|
339
367
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
//
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
case 'runCommand':
|
|
353
|
-
exec(action.command, { cwd: action.cwd });
|
|
354
|
-
break;
|
|
355
|
-
}
|
|
356
|
-
}
|
|
368
|
+
**Container composition** with `<Constraints>` and `<Contexts>`:
|
|
369
|
+
|
|
370
|
+
```tsx
|
|
371
|
+
// Extend default constraints with additional ones
|
|
372
|
+
<Constraints extend>
|
|
373
|
+
<Constraint type="must">Always include code examples.</Constraint>
|
|
374
|
+
</Constraints>
|
|
375
|
+
|
|
376
|
+
// Replace defaults entirely
|
|
377
|
+
<Constraints>
|
|
378
|
+
<Constraint type="must">Only respond in JSON.</Constraint>
|
|
379
|
+
</Constraints>
|
|
357
380
|
```
|
|
358
381
|
|
|
359
|
-
|
|
382
|
+
**Post-execution actions** — actions to perform after the LLM responds:
|
|
383
|
+
|
|
384
|
+
```tsx
|
|
385
|
+
<PostExecution>
|
|
386
|
+
<ReviewFile file="output.ts" />
|
|
387
|
+
<OpenUrl url="https://docs.example.com" />
|
|
388
|
+
<RunCommand command="npm test" />
|
|
389
|
+
</PostExecution>
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
## TypeScript Configuration
|
|
360
393
|
|
|
361
394
|
For build-time JSX transformation, configure `tsconfig.json`:
|
|
362
395
|
|
|
@@ -374,12 +407,15 @@ Or use the Babel preset for runtime transformation:
|
|
|
374
407
|
```javascript
|
|
375
408
|
// babel.config.js
|
|
376
409
|
module.exports = {
|
|
377
|
-
presets: [
|
|
378
|
-
'pupt-lib/babel-preset'
|
|
379
|
-
]
|
|
410
|
+
presets: ['pupt-lib/babel-preset'],
|
|
380
411
|
};
|
|
381
412
|
```
|
|
382
413
|
|
|
414
|
+
## Reference Documentation
|
|
415
|
+
|
|
416
|
+
- **[docs/COMPONENTS.md](docs/COMPONENTS.md)** — Full component reference (all 50+ components with all props)
|
|
417
|
+
- **[docs/API.md](docs/API.md)** — Full API reference (functions, types, base class, utilities)
|
|
418
|
+
|
|
383
419
|
## License
|
|
384
420
|
|
|
385
421
|
MIT
|