@reaatech/prompt-version-control-cli 0.1.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/CHANGELOG.md +10 -0
- package/LICENSE +21 -0
- package/README.md +164 -0
- package/dist/client.d.ts +58 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +70 -0
- package/dist/client.js.map +1 -0
- package/dist/commands/init.d.ts +8 -0
- package/dist/commands/init.d.ts.map +1 -0
- package/dist/commands/init.js +19 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/prompt.d.ts +18 -0
- package/dist/commands/prompt.d.ts.map +1 -0
- package/dist/commands/prompt.js +62 -0
- package/dist/commands/prompt.js.map +1 -0
- package/dist/commands/tag.d.ts +9 -0
- package/dist/commands/tag.d.ts.map +1 -0
- package/dist/commands/tag.js +44 -0
- package/dist/commands/tag.js.map +1 -0
- package/dist/commands/version.d.ts +9 -0
- package/dist/commands/version.d.ts.map +1 -0
- package/dist/commands/version.js +31 -0
- package/dist/commands/version.js.map +1 -0
- package/dist/config.d.ts +8 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +31 -0
- package/dist/config.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +19 -0
- package/dist/index.js.map +1 -0
- package/package.json +63 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# @reaatech/prompt-version-control-cli
|
|
2
|
+
|
|
3
|
+
## 0.1.0
|
|
4
|
+
|
|
5
|
+
### Initial release
|
|
6
|
+
|
|
7
|
+
- `pvc` binary for managing prompts, versions, and tags from the terminal
|
|
8
|
+
- `pvc init` writes `~/.pvcrc` with mode 0600
|
|
9
|
+
- Sub-commands: `prompt`, `version`, `tag`
|
|
10
|
+
- Reads `PVC_API_URL` and `PVC_API_KEY` env vars as a fallback to the config file
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 prompt-version-control contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# @reaatech/prompt-version-control-cli
|
|
2
|
+
|
|
3
|
+
[](https://www.npmjs.com/package/@reaatech/prompt-version-control-cli)
|
|
4
|
+
[](https://github.com/reaatech/prompt-version-control/blob/main/LICENSE)
|
|
5
|
+
[](https://github.com/reaatech/prompt-version-control/actions/workflows/ci.yml)
|
|
6
|
+
|
|
7
|
+
> **Status:** Pre-1.0 — APIs may change in minor versions. Pin to a specific version in production.
|
|
8
|
+
|
|
9
|
+
The `pvc` command-line tool for managing prompts, versions, and tags from the terminal. Built on [Clipanion 4](https://mael.dev/clipanion) with typed options, rich help output, and persistent configuration via `~/.pvcrc`.
|
|
10
|
+
|
|
11
|
+
## Installation
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
npm install -g @reaatech/prompt-version-control-cli
|
|
15
|
+
# or
|
|
16
|
+
pnpm add -g @reaatech/prompt-version-control-cli
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Feature Overview
|
|
20
|
+
|
|
21
|
+
- **Zero-touch setup** — `pvc init` writes a config file and you're ready
|
|
22
|
+
- **Prompt CRUD** — create, list, and retrieve prompts by ID or name
|
|
23
|
+
- **Version management** — create versions with automatic numbering
|
|
24
|
+
- **Tag lifecycle** — set `draft`, `staging`, and `production` tags by version number or ID
|
|
25
|
+
- **Persistent configuration** — `~/.pvcrc` stores API URL and key (mode 0600)
|
|
26
|
+
- **Rich CLI output** — colorized tables, error formatting, and `--help` on every command
|
|
27
|
+
- **Composable with CI/CD** — exit codes for scripting and automation
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Configure the CLI (writes ~/.pvcrc with restricted permissions)
|
|
33
|
+
pvc init --api-url http://localhost:3000 --api-key "pvc_your-api-key"
|
|
34
|
+
|
|
35
|
+
# Create a new prompt
|
|
36
|
+
pvc prompt create -n customer-support -t "You are a helpful support agent. Help with: {{issue}}"
|
|
37
|
+
|
|
38
|
+
# List all prompts
|
|
39
|
+
pvc prompt list
|
|
40
|
+
|
|
41
|
+
# Get a prompt by name or ID
|
|
42
|
+
pvc prompt get customer-support
|
|
43
|
+
|
|
44
|
+
# Create a new version (auto-increments the version number)
|
|
45
|
+
pvc version create -p customer-support -c "You are a senior support agent. Help with: {{issue}}"
|
|
46
|
+
|
|
47
|
+
# Tag version 2 as production
|
|
48
|
+
pvc tag set -p customer-support -v 2 -t production
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Commands
|
|
52
|
+
|
|
53
|
+
### `pvc init`
|
|
54
|
+
|
|
55
|
+
Initialize the CLI configuration. Writes `~/.pvcrc` with restricted file permissions (mode 0600).
|
|
56
|
+
|
|
57
|
+
| Option | Description |
|
|
58
|
+
|--------|-------------|
|
|
59
|
+
| `--api-url` | API server URL (default: `http://localhost:3000`) |
|
|
60
|
+
| `--api-key` | API key for authentication (required) |
|
|
61
|
+
|
|
62
|
+
### `pvc prompt list`
|
|
63
|
+
|
|
64
|
+
List all prompts in the project.
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
$ pvc prompt list
|
|
68
|
+
┌──────────────────────┬─────────────────────┬──────────────────────┐
|
|
69
|
+
│ ID │ Name │ Template │
|
|
70
|
+
├──────────────────────┼─────────────────────┼──────────────────────┤
|
|
71
|
+
│ prompt_abc123 │ customer-support │ You are a helpful… │
|
|
72
|
+
│ prompt_def456 │ sales-assistant │ You are a sales… │
|
|
73
|
+
└──────────────────────┴─────────────────────┴──────────────────────┘
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
### `pvc prompt create`
|
|
77
|
+
|
|
78
|
+
Create a new prompt.
|
|
79
|
+
|
|
80
|
+
| Option | Short | Description |
|
|
81
|
+
|--------|-------|-------------|
|
|
82
|
+
| `--name` | `-n` | Prompt name (required) |
|
|
83
|
+
| `--template` | `-t` | Prompt template with `{{handlebars}}` variables (required) |
|
|
84
|
+
| `--description` | `-d` | Optional description |
|
|
85
|
+
|
|
86
|
+
### `pvc prompt get <ref>`
|
|
87
|
+
|
|
88
|
+
Retrieve a prompt by ID or name. The positional argument `<ref>` is resolved against both ID and name fields.
|
|
89
|
+
|
|
90
|
+
```
|
|
91
|
+
$ pvc prompt get customer-support
|
|
92
|
+
ID: prompt_abc123
|
|
93
|
+
Name: customer-support
|
|
94
|
+
Template: You are a helpful support agent. Help with: {{issue}}
|
|
95
|
+
Created: 2026-04-15T10:30:00.000Z
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### `pvc version create`
|
|
99
|
+
|
|
100
|
+
Create a new version for a prompt. The version number is auto-incremented.
|
|
101
|
+
|
|
102
|
+
| Option | Short | Description |
|
|
103
|
+
|--------|-------|-------------|
|
|
104
|
+
| `--prompt` | `-p` | Prompt ID or name (required) |
|
|
105
|
+
| `--content` | `-c` | Version content (required) |
|
|
106
|
+
| `--template` | `-t` | Template string (defaults to `--content` if omitted) |
|
|
107
|
+
|
|
108
|
+
### `pvc tag set`
|
|
109
|
+
|
|
110
|
+
Move a tag to a specific version. Accepts the version as either a number (e.g., `2`) or a full version ID.
|
|
111
|
+
|
|
112
|
+
| Option | Short | Description |
|
|
113
|
+
|--------|-------|-------------|
|
|
114
|
+
| `--prompt` | `-p` | Prompt ID or name (required) |
|
|
115
|
+
| `--version` | `-v` | Version number or ID (required) |
|
|
116
|
+
| `--tag` | `-t` | Tag name: `draft`, `staging`, or `production` (required) |
|
|
117
|
+
|
|
118
|
+
## Configuration
|
|
119
|
+
|
|
120
|
+
The CLI persists its configuration in `~/.pvcrc` as JSON:
|
|
121
|
+
|
|
122
|
+
```json
|
|
123
|
+
{
|
|
124
|
+
"apiUrl": "http://localhost:3000",
|
|
125
|
+
"apiKey": "pvc_your-api-key",
|
|
126
|
+
"defaultProject": "my-project"
|
|
127
|
+
}
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
The file is created with mode `0600` (owner read/write only) to protect the API key.
|
|
131
|
+
|
|
132
|
+
## Usage Patterns
|
|
133
|
+
|
|
134
|
+
### CI/CD Integration
|
|
135
|
+
|
|
136
|
+
```bash
|
|
137
|
+
# In your CI pipeline, configure from environment variables
|
|
138
|
+
pvc init --api-url "$PVC_API_URL" --api-key "$PVC_API_KEY"
|
|
139
|
+
|
|
140
|
+
# Promote staging to production after tests pass
|
|
141
|
+
LATEST_VERSION=$(pvc prompt get my-assistant | jq -r '.currentVersion')
|
|
142
|
+
pvc tag set -p my-assistant -v "$LATEST_VERSION" -t production
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Automation with Exit Codes
|
|
146
|
+
|
|
147
|
+
All commands exit with code `0` on success and non-zero on failure. Combine with shell scripting:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
if ! pvc prompt get my-prompt > /dev/null 2>&1; then
|
|
151
|
+
pvc prompt create -n my-prompt -t "Default: {{input}}"
|
|
152
|
+
fi
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Related Packages
|
|
156
|
+
|
|
157
|
+
- [`@reaatech/prompt-version-control-server`](https://www.npmjs.com/package/@reaatech/prompt-version-control-server) — API server this CLI talks to
|
|
158
|
+
- [`@reaatech/prompt-version-control`](https://www.npmjs.com/package/@reaatech/prompt-version-control) — TypeScript SDK (used internally by the CLI)
|
|
159
|
+
- [`@reaatech/prompt-version-control-shared`](https://www.npmjs.com/package/@reaatech/prompt-version-control-shared) — Shared types and schemas
|
|
160
|
+
- [`@reaatech/prompt-version-control-mcp`](https://www.npmjs.com/package/@reaatech/prompt-version-control-mcp) — MCP server for AI agents
|
|
161
|
+
|
|
162
|
+
## License
|
|
163
|
+
|
|
164
|
+
[MIT](https://github.com/reaatech/prompt-version-control/blob/main/LICENSE)
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import type { PVCConfig } from './config.js';
|
|
2
|
+
export declare class APIClient {
|
|
3
|
+
private config;
|
|
4
|
+
constructor(config: PVCConfig);
|
|
5
|
+
private fetch;
|
|
6
|
+
listPrompts(): Promise<{
|
|
7
|
+
data: Array<{
|
|
8
|
+
id: string;
|
|
9
|
+
name: string;
|
|
10
|
+
}>;
|
|
11
|
+
}>;
|
|
12
|
+
getPrompt(id: string): Promise<{
|
|
13
|
+
id: string;
|
|
14
|
+
name: string;
|
|
15
|
+
template: string;
|
|
16
|
+
description: string | null;
|
|
17
|
+
variables: Record<string, unknown>;
|
|
18
|
+
}>;
|
|
19
|
+
/** Resolve a prompt id-or-name to its id, falling back to a list lookup. */
|
|
20
|
+
resolvePromptId(idOrName: string): Promise<string>;
|
|
21
|
+
listVersions(promptId: string): Promise<{
|
|
22
|
+
data: Array<{
|
|
23
|
+
id: string;
|
|
24
|
+
number: number;
|
|
25
|
+
}>;
|
|
26
|
+
}>;
|
|
27
|
+
createPrompt(data: {
|
|
28
|
+
name: string;
|
|
29
|
+
template: string;
|
|
30
|
+
description?: string;
|
|
31
|
+
variables?: Record<string, unknown>;
|
|
32
|
+
}): Promise<{
|
|
33
|
+
id: string;
|
|
34
|
+
name: string;
|
|
35
|
+
template: string;
|
|
36
|
+
}>;
|
|
37
|
+
createVersion(promptId: string, data: {
|
|
38
|
+
content: string;
|
|
39
|
+
template: string;
|
|
40
|
+
variables?: Record<string, unknown>;
|
|
41
|
+
metadata?: Record<string, unknown>;
|
|
42
|
+
}): Promise<{
|
|
43
|
+
id: string;
|
|
44
|
+
number: number;
|
|
45
|
+
content: string;
|
|
46
|
+
}>;
|
|
47
|
+
setTag(promptId: string, name: string, versionId: string): Promise<{
|
|
48
|
+
id: string;
|
|
49
|
+
name: string;
|
|
50
|
+
versionId: string;
|
|
51
|
+
}>;
|
|
52
|
+
getProduction(promptId: string): Promise<{
|
|
53
|
+
id: string;
|
|
54
|
+
number: number;
|
|
55
|
+
content: string;
|
|
56
|
+
}>;
|
|
57
|
+
}
|
|
58
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE7C,qBAAa,SAAS;IACpB,OAAO,CAAC,MAAM,CAAY;gBAEd,MAAM,EAAE,SAAS;YAIf,KAAK;IAmBb,WAAW;cACW,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,IAAI,EAAE,MAAM,CAAA;SAAE,CAAC;;IAGzD,SAAS,CAAC,EAAE,EAAE,MAAM;YAElB,MAAM;cACJ,MAAM;kBACF,MAAM;qBACH,MAAM,GAAG,IAAI;mBACf,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC;;IAItC,4EAA4E;IACtE,eAAe,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAelD,YAAY,CAAC,QAAQ,EAAE,MAAM;cACP,KAAK,CAAC;YAAE,EAAE,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE,MAAM,CAAA;SAAE,CAAC;;IAK3D,YAAY,CAAC,IAAI,EAAE;QACvB,IAAI,EAAE,MAAM,CAAC;QACb,QAAQ,EAAE,MAAM,CAAC;QACjB,WAAW,CAAC,EAAE,MAAM,CAAC;QACrB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACrC;YAEO,MAAM;cACJ,MAAM;kBACF,MAAM;;IAOd,aAAa,CACjB,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE;QACJ,OAAO,EAAE,MAAM,CAAC;QAChB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;QACpC,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;KACpC;YAGK,MAAM;gBACF,MAAM;iBACL,MAAM;;IAOb,MAAM,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM;YAEtD,MAAM;cACJ,MAAM;mBACD,MAAM;;IAOf,aAAa,CAAC,QAAQ,EAAE,MAAM;YAE5B,MAAM;gBACF,MAAM;iBACL,MAAM;;CAGpB"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export class APIClient {
|
|
2
|
+
config;
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.config = config;
|
|
5
|
+
}
|
|
6
|
+
async fetch(path, init) {
|
|
7
|
+
const res = await fetch(`${this.config.apiUrl}${path}`, {
|
|
8
|
+
...init,
|
|
9
|
+
headers: {
|
|
10
|
+
Authorization: `Bearer ${this.config.apiKey}`,
|
|
11
|
+
'Content-Type': 'application/json',
|
|
12
|
+
...init?.headers,
|
|
13
|
+
},
|
|
14
|
+
});
|
|
15
|
+
if (!res.ok) {
|
|
16
|
+
const body = (await res.json().catch(() => ({})));
|
|
17
|
+
throw new Error(body.error?.message || `HTTP ${res.status}`);
|
|
18
|
+
}
|
|
19
|
+
if (res.status === 204)
|
|
20
|
+
return undefined;
|
|
21
|
+
return res.json();
|
|
22
|
+
}
|
|
23
|
+
async listPrompts() {
|
|
24
|
+
return this.fetch('/api/v1/prompts');
|
|
25
|
+
}
|
|
26
|
+
async getPrompt(id) {
|
|
27
|
+
return this.fetch(`/api/v1/prompts/${id}`);
|
|
28
|
+
}
|
|
29
|
+
/** Resolve a prompt id-or-name to its id, falling back to a list lookup. */
|
|
30
|
+
async resolvePromptId(idOrName) {
|
|
31
|
+
try {
|
|
32
|
+
const p = await this.getPrompt(idOrName);
|
|
33
|
+
return p.id;
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
// Fall through and try by name.
|
|
37
|
+
}
|
|
38
|
+
const list = await this.listPrompts();
|
|
39
|
+
const match = list.data.find((p) => p.name === idOrName);
|
|
40
|
+
if (!match) {
|
|
41
|
+
throw new Error(`No prompt found matching '${idOrName}'`);
|
|
42
|
+
}
|
|
43
|
+
return match.id;
|
|
44
|
+
}
|
|
45
|
+
async listVersions(promptId) {
|
|
46
|
+
return this.fetch(`/api/v1/prompts/${promptId}/versions`);
|
|
47
|
+
}
|
|
48
|
+
async createPrompt(data) {
|
|
49
|
+
return this.fetch('/api/v1/prompts', {
|
|
50
|
+
method: 'POST',
|
|
51
|
+
body: JSON.stringify(data),
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
async createVersion(promptId, data) {
|
|
55
|
+
return this.fetch(`/api/v1/prompts/${promptId}/versions`, {
|
|
56
|
+
method: 'POST',
|
|
57
|
+
body: JSON.stringify(data),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
async setTag(promptId, name, versionId) {
|
|
61
|
+
return this.fetch(`/api/v1/prompts/${promptId}/tags/${name}`, {
|
|
62
|
+
method: 'POST',
|
|
63
|
+
body: JSON.stringify({ versionId }),
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
async getProduction(promptId) {
|
|
67
|
+
return this.fetch(`/api/v1/prompts/${promptId}/production`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAG5C,qBAAa,WAAY,SAAQ,OAAO;IACtC,MAAM,CAAC,KAAK,aAAc;IAE1B,MAAM,qBAAiE;IACvE,MAAM,qBAA0D;IAE1D,OAAO;CAYd"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { Command, Option } from 'clipanion';
|
|
2
|
+
import { saveConfig } from '../config.js';
|
|
3
|
+
export class InitCommand extends Command {
|
|
4
|
+
static paths = [['init']];
|
|
5
|
+
apiUrl = Option.String('--api-url', { description: 'PVC server URL' });
|
|
6
|
+
apiKey = Option.String('--api-key', { description: 'API key' });
|
|
7
|
+
async execute() {
|
|
8
|
+
const url = this.apiUrl || 'http://localhost:3000';
|
|
9
|
+
if (!this.apiKey) {
|
|
10
|
+
this.context.stdout.write('Error: --api-key is required\n');
|
|
11
|
+
return 1;
|
|
12
|
+
}
|
|
13
|
+
await saveConfig({ apiUrl: url, apiKey: this.apiKey });
|
|
14
|
+
this.context.stdout.write('Initialized PVC CLI\n');
|
|
15
|
+
this.context.stdout.write(`API URL: ${url}\n`);
|
|
16
|
+
return 0;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,WAAY,SAAQ,OAAO;IACtC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC;IAE1B,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,gBAAgB,EAAE,CAAC,CAAC;IACvE,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,WAAW,EAAE,EAAE,WAAW,EAAE,SAAS,EAAE,CAAC,CAAC;IAEhE,KAAK,CAAC,OAAO;QACX,MAAM,GAAG,GAAG,IAAI,CAAC,MAAM,IAAI,uBAAuB,CAAC;QACnD,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC;YACjB,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,gCAAgC,CAAC,CAAC;YAC5D,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,UAAU,CAAC,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE,CAAC,CAAC;QACvD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACnD,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,YAAY,GAAG,IAAI,CAAC,CAAC;QAC/C,OAAO,CAAC,CAAC;IACX,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { Command } from 'clipanion';
|
|
2
|
+
export declare class PromptListCommand extends Command {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
execute(): Promise<1 | 0>;
|
|
5
|
+
}
|
|
6
|
+
export declare class PromptCreateCommand extends Command {
|
|
7
|
+
static paths: string[][];
|
|
8
|
+
name: string | undefined;
|
|
9
|
+
template: string | undefined;
|
|
10
|
+
description: string | undefined;
|
|
11
|
+
execute(): Promise<1 | 0>;
|
|
12
|
+
}
|
|
13
|
+
export declare class PromptGetCommand extends Command {
|
|
14
|
+
static paths: string[][];
|
|
15
|
+
promptRef: string;
|
|
16
|
+
execute(): Promise<1 | 0>;
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=prompt.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.d.ts","sourceRoot":"","sources":["../../src/commands/prompt.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,qBAAa,iBAAkB,SAAQ,OAAO;IAC5C,MAAM,CAAC,KAAK,aAAwB;IAE9B,OAAO;CAcd;AAED,qBAAa,mBAAoB,SAAQ,OAAO;IAC9C,MAAM,CAAC,KAAK,aAA0B;IAEtC,IAAI,qBAA8D;IAClE,QAAQ,qBAAuE;IAC/E,WAAW,qBAAqE;IAE1E,OAAO;CAoBd;AAED,qBAAa,gBAAiB,SAAQ,OAAO;IAC3C,MAAM,CAAC,KAAK,aAAuB;IAGnC,SAAS,SAAqC;IAExC,OAAO;CAad"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { Command, Option } from 'clipanion';
|
|
2
|
+
import { APIClient } from '../client.js';
|
|
3
|
+
import { loadConfig } from '../config.js';
|
|
4
|
+
export class PromptListCommand extends Command {
|
|
5
|
+
static paths = [['prompt', 'list']];
|
|
6
|
+
async execute() {
|
|
7
|
+
const config = await loadConfig();
|
|
8
|
+
if (!config) {
|
|
9
|
+
this.context.stdout.write('Run `pvc init` first\n');
|
|
10
|
+
return 1;
|
|
11
|
+
}
|
|
12
|
+
const client = new APIClient(config);
|
|
13
|
+
const prompts = await client.listPrompts();
|
|
14
|
+
for (const p of prompts.data) {
|
|
15
|
+
this.context.stdout.write(`${p.id}\t${p.name}\n`);
|
|
16
|
+
}
|
|
17
|
+
return 0;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export class PromptCreateCommand extends Command {
|
|
21
|
+
static paths = [['prompt', 'create']];
|
|
22
|
+
name = Option.String('-n,--name', { description: 'Prompt name' });
|
|
23
|
+
template = Option.String('-t,--template', { description: 'Template content' });
|
|
24
|
+
description = Option.String('-d,--description', { description: 'Description' });
|
|
25
|
+
async execute() {
|
|
26
|
+
const config = await loadConfig();
|
|
27
|
+
if (!config) {
|
|
28
|
+
this.context.stdout.write('Run `pvc init` first\n');
|
|
29
|
+
return 1;
|
|
30
|
+
}
|
|
31
|
+
if (!this.name || !this.template) {
|
|
32
|
+
this.context.stdout.write('Both --name and --template are required\n');
|
|
33
|
+
return 1;
|
|
34
|
+
}
|
|
35
|
+
const client = new APIClient(config);
|
|
36
|
+
const prompt = await client.createPrompt({
|
|
37
|
+
name: this.name,
|
|
38
|
+
template: this.template,
|
|
39
|
+
description: this.description,
|
|
40
|
+
});
|
|
41
|
+
this.context.stdout.write(`Created prompt: ${prompt.id}\n`);
|
|
42
|
+
return 0;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export class PromptGetCommand extends Command {
|
|
46
|
+
static paths = [['prompt', 'get']];
|
|
47
|
+
// Accept id-or-name; resolve name → id transparently.
|
|
48
|
+
promptRef = Option.String({ required: true });
|
|
49
|
+
async execute() {
|
|
50
|
+
const config = await loadConfig();
|
|
51
|
+
if (!config) {
|
|
52
|
+
this.context.stdout.write('Run `pvc init` first\n');
|
|
53
|
+
return 1;
|
|
54
|
+
}
|
|
55
|
+
const client = new APIClient(config);
|
|
56
|
+
const promptId = await client.resolvePromptId(this.promptRef);
|
|
57
|
+
const prompt = await client.getPrompt(promptId);
|
|
58
|
+
this.context.stdout.write(`${JSON.stringify(prompt, null, 2)}\n`);
|
|
59
|
+
return 0;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=prompt.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt.js","sourceRoot":"","sources":["../../src/commands/prompt.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from 'clipanion';
|
|
2
|
+
export declare class TagSetCommand extends Command {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
prompt: string | undefined;
|
|
5
|
+
version: string | undefined;
|
|
6
|
+
tag: string | undefined;
|
|
7
|
+
execute(): Promise<1 | 0>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=tag.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.d.ts","sourceRoot":"","sources":["../../src/commands/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,qBAAa,aAAc,SAAQ,OAAO;IACxC,MAAM,CAAC,KAAK,aAAoB;IAEhC,MAAM,qBAAsE;IAE5E,OAAO,qBAEJ;IAEH,GAAG,qBAEA;IAEG,OAAO;CA+Bd"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Command, Option } from 'clipanion';
|
|
2
|
+
import { APIClient } from '../client.js';
|
|
3
|
+
import { loadConfig } from '../config.js';
|
|
4
|
+
export class TagSetCommand extends Command {
|
|
5
|
+
static paths = [['tag', 'set']];
|
|
6
|
+
prompt = Option.String('-p,--prompt', { description: 'Prompt id or name' });
|
|
7
|
+
// Accept either --version <number-or-id> or the legacy -v alias.
|
|
8
|
+
version = Option.String('-v,--version', {
|
|
9
|
+
description: 'Version number or id',
|
|
10
|
+
});
|
|
11
|
+
// Tag is the canonical spelling per README; -n/--name kept as an alias.
|
|
12
|
+
tag = Option.String('-t,--tag,-n,--name', {
|
|
13
|
+
description: 'Tag name (draft/staging/production)',
|
|
14
|
+
});
|
|
15
|
+
async execute() {
|
|
16
|
+
const config = await loadConfig();
|
|
17
|
+
if (!config) {
|
|
18
|
+
this.context.stdout.write('Run `pvc init` first\n');
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
if (!this.prompt || !this.version || !this.tag) {
|
|
22
|
+
this.context.stdout.write('Required: --prompt, --version, --tag\n');
|
|
23
|
+
return 1;
|
|
24
|
+
}
|
|
25
|
+
const client = new APIClient(config);
|
|
26
|
+
const promptId = await client.resolvePromptId(this.prompt);
|
|
27
|
+
// Allow `--version 2` (number) by resolving it to a version id.
|
|
28
|
+
let versionId = this.version;
|
|
29
|
+
if (/^\d+$/.test(this.version)) {
|
|
30
|
+
const number = Number(this.version);
|
|
31
|
+
const versions = await client.listVersions(promptId);
|
|
32
|
+
const match = versions.data.find((v) => v.number === number);
|
|
33
|
+
if (!match) {
|
|
34
|
+
this.context.stdout.write(`No version #${number} for prompt ${this.prompt}\n`);
|
|
35
|
+
return 1;
|
|
36
|
+
}
|
|
37
|
+
versionId = match.id;
|
|
38
|
+
}
|
|
39
|
+
const result = await client.setTag(promptId, this.tag, versionId);
|
|
40
|
+
this.context.stdout.write(`Set ${result.name} on ${this.prompt} → ${result.versionId}\n`);
|
|
41
|
+
return 0;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=tag.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tag.js","sourceRoot":"","sources":["../../src/commands/tag.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,aAAc,SAAQ,OAAO;IACxC,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC,CAAC;IAEhC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC5E,iEAAiE;IACjE,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE;QACtC,WAAW,EAAE,sBAAsB;KACpC,CAAC,CAAC;IACH,wEAAwE;IACxE,GAAG,GAAG,MAAM,CAAC,MAAM,CAAC,oBAAoB,EAAE;QACxC,WAAW,EAAE,qCAAqC;KACnD,CAAC,CAAC;IAEH,KAAK,CAAC,OAAO;QACX,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wCAAwC,CAAC,CAAC;YACpE,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAE3D,gEAAgE;QAChE,IAAI,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC;QAC7B,IAAI,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACpC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC;YACrD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC;YAC7D,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,MAAM,eAAe,IAAI,CAAC,MAAM,IAAI,CAAC,CAAC;gBAC/E,OAAO,CAAC,CAAC;YACX,CAAC;YACD,SAAS,GAAG,KAAK,CAAC,EAAE,CAAC;QACvB,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,QAAQ,EAAE,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QAClE,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,OAAO,MAAM,CAAC,IAAI,OAAO,IAAI,CAAC,MAAM,MAAM,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC;QAC1F,OAAO,CAAC,CAAC;IACX,CAAC"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Command } from 'clipanion';
|
|
2
|
+
export declare class VersionCreateCommand extends Command {
|
|
3
|
+
static paths: string[][];
|
|
4
|
+
prompt: string | undefined;
|
|
5
|
+
content: string | undefined;
|
|
6
|
+
template: string | undefined;
|
|
7
|
+
execute(): Promise<1 | 0>;
|
|
8
|
+
}
|
|
9
|
+
//# sourceMappingURL=version.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAI5C,qBAAa,oBAAqB,SAAQ,OAAO;IAC/C,MAAM,CAAC,KAAK,aAA2B;IAEvC,MAAM,qBAAsE;IAC5E,OAAO,qBAAqE;IAC5E,QAAQ,qBAEL;IAEG,OAAO;CAoBd"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { Command, Option } from 'clipanion';
|
|
2
|
+
import { APIClient } from '../client.js';
|
|
3
|
+
import { loadConfig } from '../config.js';
|
|
4
|
+
export class VersionCreateCommand extends Command {
|
|
5
|
+
static paths = [['version', 'create']];
|
|
6
|
+
prompt = Option.String('-p,--prompt', { description: 'Prompt id or name' });
|
|
7
|
+
content = Option.String('-c,--content', { description: 'Version content' });
|
|
8
|
+
template = Option.String('-t,--template', {
|
|
9
|
+
description: 'Template (defaults to --content if omitted)',
|
|
10
|
+
});
|
|
11
|
+
async execute() {
|
|
12
|
+
const config = await loadConfig();
|
|
13
|
+
if (!config) {
|
|
14
|
+
this.context.stdout.write('Run `pvc init` first\n');
|
|
15
|
+
return 1;
|
|
16
|
+
}
|
|
17
|
+
if (!this.prompt || !this.content) {
|
|
18
|
+
this.context.stdout.write('Both --prompt and --content are required\n');
|
|
19
|
+
return 1;
|
|
20
|
+
}
|
|
21
|
+
const client = new APIClient(config);
|
|
22
|
+
const promptId = await client.resolvePromptId(this.prompt);
|
|
23
|
+
const version = await client.createVersion(promptId, {
|
|
24
|
+
content: this.content,
|
|
25
|
+
template: this.template ?? this.content,
|
|
26
|
+
});
|
|
27
|
+
this.context.stdout.write(`Created version ${version.number}: ${version.id}\n`);
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=version.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/commands/version.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,MAAM,WAAW,CAAC;AAC5C,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,MAAM,OAAO,oBAAqB,SAAQ,OAAO;IAC/C,MAAM,CAAC,KAAK,GAAG,CAAC,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC,CAAC;IAEvC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC,aAAa,EAAE,EAAE,WAAW,EAAE,mBAAmB,EAAE,CAAC,CAAC;IAC5E,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,cAAc,EAAE,EAAE,WAAW,EAAE,iBAAiB,EAAE,CAAC,CAAC;IAC5E,QAAQ,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,EAAE;QACxC,WAAW,EAAE,6CAA6C;KAC3D,CAAC,CAAC;IAEH,KAAK,CAAC,OAAO;QACX,MAAM,MAAM,GAAG,MAAM,UAAU,EAAE,CAAC;QAClC,IAAI,CAAC,MAAM,EAAE,CAAC;YACZ,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,wBAAwB,CAAC,CAAC;YACpD,OAAO,CAAC,CAAC;QACX,CAAC;QACD,IAAI,CAAC,IAAI,CAAC,MAAM,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,CAAC;YAClC,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,4CAA4C,CAAC,CAAC;YACxE,OAAO,CAAC,CAAC;QACX,CAAC;QAED,MAAM,MAAM,GAAG,IAAI,SAAS,CAAC,MAAM,CAAC,CAAC;QACrC,MAAM,QAAQ,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAC3D,MAAM,OAAO,GAAG,MAAM,MAAM,CAAC,aAAa,CAAC,QAAQ,EAAE;YACnD,OAAO,EAAE,IAAI,CAAC,OAAO;YACrB,QAAQ,EAAE,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,OAAO;SACxC,CAAC,CAAC;QACH,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,mBAAmB,OAAO,CAAC,MAAM,KAAK,OAAO,CAAC,EAAE,IAAI,CAAC,CAAC;QAChF,OAAO,CAAC,CAAC;IACX,CAAC"}
|
package/dist/config.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface PVCConfig {
|
|
2
|
+
apiUrl: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
defaultProject?: string;
|
|
5
|
+
}
|
|
6
|
+
export declare function loadConfig(): Promise<PVCConfig | null>;
|
|
7
|
+
export declare function saveConfig(config: PVCConfig): Promise<void>;
|
|
8
|
+
//# sourceMappingURL=config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,SAAS;IACxB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAUD,wBAAsB,UAAU,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAO5D;AAED,wBAAsB,UAAU,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CASjE"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { chmod, readFile, writeFile } from 'node:fs/promises';
|
|
2
|
+
import { homedir } from 'node:os';
|
|
3
|
+
import { join } from 'node:path';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
const ConfigSchema = z.object({
|
|
6
|
+
apiUrl: z.string().url(),
|
|
7
|
+
apiKey: z.string().min(1),
|
|
8
|
+
defaultProject: z.string().optional(),
|
|
9
|
+
});
|
|
10
|
+
const CONFIG_PATH = join(homedir(), '.pvcrc');
|
|
11
|
+
export async function loadConfig() {
|
|
12
|
+
try {
|
|
13
|
+
const data = await readFile(CONFIG_PATH, 'utf8');
|
|
14
|
+
return ConfigSchema.parse(JSON.parse(data));
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return null;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
export async function saveConfig(config) {
|
|
21
|
+
await writeFile(CONFIG_PATH, JSON.stringify(config, null, 2));
|
|
22
|
+
// Restrict permissions: API key must not be world-readable. Best-effort —
|
|
23
|
+
// some filesystems (e.g. Windows) ignore POSIX modes.
|
|
24
|
+
try {
|
|
25
|
+
await chmod(CONFIG_PATH, 0o600);
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
// ignore
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=config.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAQxB,MAAM,YAAY,GAAG,CAAC,CAAC,MAAM,CAAC;IAC5B,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE;IACxB,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IACzB,cAAc,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;CACtC,CAAC,CAAC;AAEH,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,EAAE,QAAQ,CAAC,CAAC;AAE9C,MAAM,CAAC,KAAK,UAAU,UAAU;IAC9B,IAAI,CAAC;QACH,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC,CAAC;QACjD,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;IAC9C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,MAAiB;IAChD,MAAM,SAAS,CAAC,WAAW,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;IAC9D,0EAA0E;IAC1E,sDAAsD;IACtD,IAAI,CAAC;QACH,MAAM,KAAK,CAAC,WAAW,EAAE,KAAK,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,SAAS;IACX,CAAC;AACH,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":""}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Cli } from 'clipanion';
|
|
3
|
+
import { InitCommand } from './commands/init.js';
|
|
4
|
+
import { PromptCreateCommand, PromptGetCommand, PromptListCommand } from './commands/prompt.js';
|
|
5
|
+
import { TagSetCommand } from './commands/tag.js';
|
|
6
|
+
import { VersionCreateCommand } from './commands/version.js';
|
|
7
|
+
const cli = new Cli({
|
|
8
|
+
binaryLabel: 'Prompt Version Control CLI',
|
|
9
|
+
binaryName: 'pvc',
|
|
10
|
+
binaryVersion: '0.1.0',
|
|
11
|
+
});
|
|
12
|
+
cli.register(InitCommand);
|
|
13
|
+
cli.register(PromptListCommand);
|
|
14
|
+
cli.register(PromptCreateCommand);
|
|
15
|
+
cli.register(PromptGetCommand);
|
|
16
|
+
cli.register(VersionCreateCommand);
|
|
17
|
+
cli.register(TagSetCommand);
|
|
18
|
+
cli.runExit(process.argv.slice(2));
|
|
19
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAChC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,uBAAuB,CAAC;AAE7D,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC;IAClB,WAAW,EAAE,4BAA4B;IACzC,UAAU,EAAE,KAAK;IACjB,aAAa,EAAE,OAAO;CACvB,CAAC,CAAC;AAEH,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;AAC1B,GAAG,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAC;AAChC,GAAG,CAAC,QAAQ,CAAC,mBAAmB,CAAC,CAAC;AAClC,GAAG,CAAC,QAAQ,CAAC,gBAAgB,CAAC,CAAC;AAC/B,GAAG,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC;AACnC,GAAG,CAAC,QAAQ,CAAC,aAAa,CAAC,CAAC;AAE5B,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@reaatech/prompt-version-control-cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Prompt Version Control CLI",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Rick Somers <rick@reaatech.com> (https://reaatech.com)",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "https://github.com/reaatech/prompt-version-control.git",
|
|
10
|
+
"directory": "packages/cli"
|
|
11
|
+
},
|
|
12
|
+
"bugs": {
|
|
13
|
+
"url": "https://github.com/reaatech/prompt-version-control/issues"
|
|
14
|
+
},
|
|
15
|
+
"homepage": "https://github.com/reaatech/prompt-version-control/tree/main/packages/cli#readme",
|
|
16
|
+
"keywords": [
|
|
17
|
+
"prompt",
|
|
18
|
+
"version-control",
|
|
19
|
+
"cli"
|
|
20
|
+
],
|
|
21
|
+
"type": "module",
|
|
22
|
+
"engines": {
|
|
23
|
+
"node": ">=22"
|
|
24
|
+
},
|
|
25
|
+
"bin": {
|
|
26
|
+
"pvc": "./dist/index.js"
|
|
27
|
+
},
|
|
28
|
+
"main": "./dist/index.js",
|
|
29
|
+
"types": "./dist/index.d.ts",
|
|
30
|
+
"exports": {
|
|
31
|
+
".": {
|
|
32
|
+
"types": "./dist/index.d.ts",
|
|
33
|
+
"import": "./dist/index.js"
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"files": [
|
|
37
|
+
"dist",
|
|
38
|
+
"CHANGELOG.md"
|
|
39
|
+
],
|
|
40
|
+
"publishConfig": {
|
|
41
|
+
"access": "public"
|
|
42
|
+
},
|
|
43
|
+
"dependencies": {
|
|
44
|
+
"clipanion": "^4.0.0-rc.4",
|
|
45
|
+
"typanion": "^3.14.0",
|
|
46
|
+
"zod": "^3.22.0",
|
|
47
|
+
"@reaatech/prompt-version-control-shared": "0.1.0",
|
|
48
|
+
"@reaatech/prompt-version-control": "0.1.0"
|
|
49
|
+
},
|
|
50
|
+
"devDependencies": {
|
|
51
|
+
"@types/node": "^25.8.0",
|
|
52
|
+
"tsx": "^4.22.1",
|
|
53
|
+
"typescript": "^5.8.3",
|
|
54
|
+
"vitest": "^3.1.1"
|
|
55
|
+
},
|
|
56
|
+
"scripts": {
|
|
57
|
+
"build": "tsc",
|
|
58
|
+
"dev": "tsx watch src/index.ts",
|
|
59
|
+
"test": "vitest run",
|
|
60
|
+
"test:coverage": "vitest run --coverage",
|
|
61
|
+
"clean": "rm -rf dist coverage .turbo *.tsbuildinfo"
|
|
62
|
+
}
|
|
63
|
+
}
|