@praxis-framework/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/README.md +51 -0
- package/dist/app.js +122 -0
- package/dist/app.js.map +1 -0
- package/dist/commands/init-config.js +85 -0
- package/dist/commands/init-config.js.map +1 -0
- package/dist/commands/init.js +59 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/log.js +171 -0
- package/dist/commands/log.js.map +1 -0
- package/dist/flows/capabilities.js +14 -0
- package/dist/flows/capabilities.js.map +1 -0
- package/dist/flows/inhibitions.js +14 -0
- package/dist/flows/inhibitions.js.map +1 -0
- package/dist/flows/initial-verbs.js +82 -0
- package/dist/flows/initial-verbs.js.map +1 -0
- package/dist/flows/organisation.js +112 -0
- package/dist/flows/organisation.js.map +1 -0
- package/dist/flows/path-choice.js +22 -0
- package/dist/flows/path-choice.js.map +1 -0
- package/dist/flows/review.js +31 -0
- package/dist/flows/review.js.map +1 -0
- package/dist/flows/role-definition.js +77 -0
- package/dist/flows/role-definition.js.map +1 -0
- package/dist/flows/tools.js +63 -0
- package/dist/flows/tools.js.map +1 -0
- package/dist/flows/voice.js +146 -0
- package/dist/flows/voice.js.map +1 -0
- package/dist/flows/welcome.js +17 -0
- package/dist/flows/welcome.js.map +1 -0
- package/dist/flows/wrote.js +51 -0
- package/dist/flows/wrote.js.map +1 -0
- package/dist/index.js +57 -0
- package/dist/index.js.map +1 -0
- package/dist/lib/catalog.js +190 -0
- package/dist/lib/catalog.js.map +1 -0
- package/dist/lib/seed-adapter.js +28 -0
- package/dist/lib/seed-adapter.js.map +1 -0
- package/dist/lib/traits.js +13 -0
- package/dist/lib/traits.js.map +1 -0
- package/dist/state/form.js +63 -0
- package/dist/state/form.js.map +1 -0
- package/dist/state/steps.js +28 -0
- package/dist/state/steps.js.map +1 -0
- package/dist/ui/header.js +14 -0
- package/dist/ui/header.js.map +1 -0
- package/dist/ui/list-builder-state.js +179 -0
- package/dist/ui/list-builder-state.js.map +1 -0
- package/dist/ui/list-builder.js +144 -0
- package/dist/ui/list-builder.js.map +1 -0
- package/dist/ui/theme.js +8 -0
- package/dist/ui/theme.js.map +1 -0
- package/examples/sample-role.json +24 -0
- package/package.json +66 -0
package/dist/index.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { program } from 'commander';
|
|
3
|
+
import { initCommand } from './commands/init.js';
|
|
4
|
+
import { LogError, runLog } from './commands/log.js';
|
|
5
|
+
program
|
|
6
|
+
.name('praxis')
|
|
7
|
+
.description('praxis-framework CLI')
|
|
8
|
+
.version('0.0.1');
|
|
9
|
+
program
|
|
10
|
+
.command('init')
|
|
11
|
+
.description('set up a new praxis role')
|
|
12
|
+
.option('--path <path>', 'directory to scaffold the role into', process.cwd())
|
|
13
|
+
.option('--config <file>', 'seed non-interactively from a JSON file matching SeedInput (see cli/examples/sample-role.json)')
|
|
14
|
+
.option('--overwrite', 'overwrite existing files at the target (only with --config)', false)
|
|
15
|
+
.addHelpText('after', `
|
|
16
|
+
Examples:
|
|
17
|
+
$ praxis init # interactive wizard
|
|
18
|
+
$ praxis init --config ./role.json --path ./my-role # non-interactive seed
|
|
19
|
+
$ praxis init --config ./role.json --overwrite # re-seed an existing dir
|
|
20
|
+
|
|
21
|
+
A sample config lives at cli/examples/sample-role.json — copy and edit it
|
|
22
|
+
as a starting template for the non-interactive flow.
|
|
23
|
+
`)
|
|
24
|
+
.action(initCommand);
|
|
25
|
+
program
|
|
26
|
+
.command('log')
|
|
27
|
+
.description("append a JSONL entry to today's log")
|
|
28
|
+
.option('--campaign <id>', 'campaign id (logs land under campaigns/{id}/logs/)')
|
|
29
|
+
.option('--agent <name>', 'agent / verb name responsible for the action')
|
|
30
|
+
.option('--action <verb>', 'action verb, e.g. email_drafted, decision')
|
|
31
|
+
.option('--prospect <id>', 'prospect id (optional conventional extra)')
|
|
32
|
+
.option('--details <text>', 'short narrative (optional)')
|
|
33
|
+
.option('--subject <text>', 'email/message subject (optional)')
|
|
34
|
+
.option('--echo', 'print the JSON line that was written', false)
|
|
35
|
+
.argument('[extras...]', 'extra key=value pairs to merge into the entry')
|
|
36
|
+
.addHelpText('after', `
|
|
37
|
+
Examples:
|
|
38
|
+
$ praxis log --campaign=q1-outreach --agent=draft-emails --action=email_drafted
|
|
39
|
+
$ praxis log --campaign=manual-leads --agent=monitor-channels --action=channel_intake \\
|
|
40
|
+
channel=notifications-searchai message_ts=1234.5
|
|
41
|
+
`)
|
|
42
|
+
.action(async (extras, options) => {
|
|
43
|
+
try {
|
|
44
|
+
await runLog(options, extras);
|
|
45
|
+
}
|
|
46
|
+
catch (err) {
|
|
47
|
+
if (err instanceof LogError) {
|
|
48
|
+
process.stderr.write(`${err.message}\n`);
|
|
49
|
+
process.exit(1);
|
|
50
|
+
}
|
|
51
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
52
|
+
process.stderr.write(`praxis log: ${message}\n`);
|
|
53
|
+
process.exit(1);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
program.parse();
|
|
57
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,QAAQ,EAAE,MAAM,EAA0B,MAAM,mBAAmB,CAAC;AAE7E,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,sBAAsB,CAAC;KACnC,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,OAAO;KACJ,OAAO,CAAC,MAAM,CAAC;KACf,WAAW,CAAC,0BAA0B,CAAC;KACvC,MAAM,CAAC,eAAe,EAAE,qCAAqC,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;KAC7E,MAAM,CACL,iBAAiB,EACjB,gGAAgG,CACjG;KACA,MAAM,CAAC,aAAa,EAAE,6DAA6D,EAAE,KAAK,CAAC;KAC3F,WAAW,CACV,OAAO,EACP;;;;;;;;CAQH,CACE;KACA,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,KAAK,CAAC;KACd,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,iBAAiB,EAAE,oDAAoD,CAAC;KAC/E,MAAM,CAAC,gBAAgB,EAAE,8CAA8C,CAAC;KACxE,MAAM,CAAC,iBAAiB,EAAE,2CAA2C,CAAC;KACtE,MAAM,CAAC,iBAAiB,EAAE,2CAA2C,CAAC;KACtE,MAAM,CAAC,kBAAkB,EAAE,4BAA4B,CAAC;KACxD,MAAM,CAAC,kBAAkB,EAAE,kCAAkC,CAAC;KAC9D,MAAM,CAAC,QAAQ,EAAE,sCAAsC,EAAE,KAAK,CAAC;KAC/D,QAAQ,CAAC,aAAa,EAAE,+CAA+C,CAAC;KACxE,WAAW,CACV,OAAO,EACP;;;;;CAKH,CACE;KACA,MAAM,CAAC,KAAK,EAAE,MAAgB,EAAE,OAA0B,EAAE,EAAE;IAC7D,IAAI,CAAC;QACH,MAAM,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;IAChC,CAAC;IAAC,OAAO,GAAY,EAAE,CAAC;QACtB,IAAI,GAAG,YAAY,QAAQ,EAAE,CAAC;YAC5B,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC;YACzC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;QACD,MAAM,OAAO,GAAG,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC;QACjE,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,eAAe,OAAO,IAAI,CAAC,CAAC;QACjD,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC;AACH,CAAC,CAAC,CAAC;AAEL,OAAO,CAAC,KAAK,EAAE,CAAC"}
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
import fs from 'node:fs/promises';
|
|
2
|
+
import path from 'node:path';
|
|
3
|
+
import { resolveTemplatePath } from '@praxis-framework/seed';
|
|
4
|
+
import { z } from 'zod';
|
|
5
|
+
/**
|
|
6
|
+
* Framework-level catalog of tool capabilities that roles can opt into.
|
|
7
|
+
*
|
|
8
|
+
* Roles declare which capabilities they need per-agent; the runtime maps
|
|
9
|
+
* capabilities to concrete adapters at startup. The CLI's `praxis init`
|
|
10
|
+
* wizard surfaces the optional ones for operator selection.
|
|
11
|
+
*/
|
|
12
|
+
export const CapabilitySchema = z
|
|
13
|
+
.object({
|
|
14
|
+
description: z.string(),
|
|
15
|
+
transport_options: z.array(z.string()).min(1),
|
|
16
|
+
default_transport: z.string(),
|
|
17
|
+
always_available: z.boolean().optional().default(false),
|
|
18
|
+
default_auth_env: z.string().nullable().optional(),
|
|
19
|
+
docker_image: z.string().optional(),
|
|
20
|
+
})
|
|
21
|
+
// Permissive on unknown fields — schema may grow without breaking older CLIs.
|
|
22
|
+
.passthrough();
|
|
23
|
+
/**
|
|
24
|
+
* Resolve `<template-root>/lib/tools.yaml` by delegating to the seed package's
|
|
25
|
+
* template resolver. The seed package owns template-path resolution: it
|
|
26
|
+
* checks `<package-root>/template/` first (the published-mode layout, where
|
|
27
|
+
* the template ships inside the seed tarball), then walks up looking for a
|
|
28
|
+
* sibling `template/` directory (the dev-monorepo layout). Using its
|
|
29
|
+
* resolver here keeps both packages in lockstep on where the template lives.
|
|
30
|
+
*/
|
|
31
|
+
function catalogPath() {
|
|
32
|
+
return path.join(resolveTemplatePath(), 'lib', 'tools.yaml');
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Load the framework catalog from `template/lib/tools.yaml`. Throws if the
|
|
36
|
+
* file is missing or unparseable — the CLI cannot function without it.
|
|
37
|
+
*/
|
|
38
|
+
export async function loadCatalog() {
|
|
39
|
+
const CATALOG_PATH = catalogPath();
|
|
40
|
+
let text;
|
|
41
|
+
try {
|
|
42
|
+
text = await fs.readFile(CATALOG_PATH, 'utf-8');
|
|
43
|
+
}
|
|
44
|
+
catch (e) {
|
|
45
|
+
const cause = e instanceof Error ? e.message : String(e);
|
|
46
|
+
throw new Error(`praxis catalog not found at ${CATALOG_PATH}: ${cause}`);
|
|
47
|
+
}
|
|
48
|
+
return parseCatalog(text);
|
|
49
|
+
}
|
|
50
|
+
/** Parse a catalog YAML payload. Exported for tests. */
|
|
51
|
+
export function parseCatalog(text) {
|
|
52
|
+
const raw = parseToolsYaml(text);
|
|
53
|
+
const capabilities = [];
|
|
54
|
+
for (const [name, fields] of Object.entries(raw)) {
|
|
55
|
+
const result = CapabilitySchema.safeParse(fields);
|
|
56
|
+
if (!result.success) {
|
|
57
|
+
throw new Error(`praxis catalog: invalid entry "${name}" — ${result.error.issues
|
|
58
|
+
.map((i) => `${i.path.join('.') || '<root>'}: ${i.message}`)
|
|
59
|
+
.join('; ')}`);
|
|
60
|
+
}
|
|
61
|
+
const cap = {
|
|
62
|
+
name,
|
|
63
|
+
description: result.data.description,
|
|
64
|
+
transport_options: result.data.transport_options,
|
|
65
|
+
default_transport: result.data.default_transport,
|
|
66
|
+
always_available: result.data.always_available,
|
|
67
|
+
};
|
|
68
|
+
if (result.data.default_auth_env !== undefined) {
|
|
69
|
+
cap.default_auth_env = result.data.default_auth_env;
|
|
70
|
+
}
|
|
71
|
+
if (result.data.docker_image !== undefined) {
|
|
72
|
+
cap.docker_image = result.data.docker_image;
|
|
73
|
+
}
|
|
74
|
+
capabilities.push(cap);
|
|
75
|
+
}
|
|
76
|
+
if (capabilities.length === 0) {
|
|
77
|
+
throw new Error('praxis catalog: no capabilities defined in tools.yaml');
|
|
78
|
+
}
|
|
79
|
+
return {
|
|
80
|
+
capabilities,
|
|
81
|
+
builtins: () => capabilities.filter((c) => c.always_available),
|
|
82
|
+
optional: () => capabilities.filter((c) => !c.always_available),
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
export function parseToolsYaml(text) {
|
|
86
|
+
const lines = text.split('\n');
|
|
87
|
+
const out = {};
|
|
88
|
+
let i = 0;
|
|
89
|
+
let inCapabilities = false;
|
|
90
|
+
let currentCap = null;
|
|
91
|
+
let currentCapIndent = 0;
|
|
92
|
+
let fieldIndent = null;
|
|
93
|
+
while (i < lines.length) {
|
|
94
|
+
const raw = lines[i] ?? '';
|
|
95
|
+
const trimmed = raw.trim();
|
|
96
|
+
// Skip blanks and comments at any depth.
|
|
97
|
+
if (trimmed.length === 0 || trimmed.startsWith('#')) {
|
|
98
|
+
i += 1;
|
|
99
|
+
continue;
|
|
100
|
+
}
|
|
101
|
+
if (!inCapabilities) {
|
|
102
|
+
if (/^capabilities\s*:\s*$/.test(trimmed)) {
|
|
103
|
+
inCapabilities = true;
|
|
104
|
+
}
|
|
105
|
+
i += 1;
|
|
106
|
+
continue;
|
|
107
|
+
}
|
|
108
|
+
const leading = raw.length - raw.trimStart().length;
|
|
109
|
+
// A new top-level key (zero indent) ends the capabilities block.
|
|
110
|
+
if (leading === 0 && /:\s*$/.test(trimmed)) {
|
|
111
|
+
break;
|
|
112
|
+
}
|
|
113
|
+
// Capability header: `<name>:` at the first indent level under
|
|
114
|
+
// `capabilities:`. The header line has the form `<indent><name>:` (line
|
|
115
|
+
// ends with `:` and nothing after) and the indent is the same as (or
|
|
116
|
+
// first establishes) the capability indent. The name itself may contain
|
|
117
|
+
// colons — `mcp:slack:` is `mcp:slack` followed by the trailing `:`.
|
|
118
|
+
const isHeaderLine = trimmed.endsWith(':') && !trimmed.startsWith('-');
|
|
119
|
+
if (isHeaderLine && (currentCap === null || leading <= currentCapIndent)) {
|
|
120
|
+
const name = trimmed.slice(0, -1).trim();
|
|
121
|
+
if (name.length > 0) {
|
|
122
|
+
currentCap = name;
|
|
123
|
+
currentCapIndent = leading;
|
|
124
|
+
fieldIndent = null;
|
|
125
|
+
out[name] = {};
|
|
126
|
+
i += 1;
|
|
127
|
+
continue;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
// Field under the current capability.
|
|
131
|
+
if (currentCap !== null && leading > currentCapIndent) {
|
|
132
|
+
if (fieldIndent === null)
|
|
133
|
+
fieldIndent = leading;
|
|
134
|
+
const fieldMatch = /^\s*([A-Za-z_][A-Za-z0-9_]*)\s*:\s*(.*)$/.exec(raw);
|
|
135
|
+
if (fieldMatch) {
|
|
136
|
+
const key = (fieldMatch[1] ?? '').trim();
|
|
137
|
+
const rest = (fieldMatch[2] ?? '').trim();
|
|
138
|
+
out[currentCap][key] = parseScalar(rest);
|
|
139
|
+
}
|
|
140
|
+
i += 1;
|
|
141
|
+
continue;
|
|
142
|
+
}
|
|
143
|
+
i += 1;
|
|
144
|
+
}
|
|
145
|
+
return out;
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Parse a YAML scalar / inline-list value. Handles:
|
|
149
|
+
* - empty → null
|
|
150
|
+
* - `null` / `~` → null
|
|
151
|
+
* - `true` / `false` → boolean
|
|
152
|
+
* - `[a, b, c]` → string[]
|
|
153
|
+
* - quoted "string" → string (quotes stripped)
|
|
154
|
+
* - bare string → string
|
|
155
|
+
* - integer literal → number
|
|
156
|
+
*/
|
|
157
|
+
function parseScalar(raw) {
|
|
158
|
+
const value = raw.trim();
|
|
159
|
+
if (value.length === 0)
|
|
160
|
+
return null;
|
|
161
|
+
if (value === 'null' || value === '~')
|
|
162
|
+
return null;
|
|
163
|
+
if (value === 'true')
|
|
164
|
+
return true;
|
|
165
|
+
if (value === 'false')
|
|
166
|
+
return false;
|
|
167
|
+
if (value.startsWith('[') && value.endsWith(']')) {
|
|
168
|
+
const inner = value.slice(1, -1).trim();
|
|
169
|
+
if (inner.length === 0)
|
|
170
|
+
return [];
|
|
171
|
+
return inner.split(',').map((part) => stripQuotes(part.trim()));
|
|
172
|
+
}
|
|
173
|
+
if (/^-?\d+$/.test(value)) {
|
|
174
|
+
const n = Number.parseInt(value, 10);
|
|
175
|
+
if (Number.isFinite(n))
|
|
176
|
+
return n;
|
|
177
|
+
}
|
|
178
|
+
return stripQuotes(value);
|
|
179
|
+
}
|
|
180
|
+
function stripQuotes(value) {
|
|
181
|
+
if (value.length < 2)
|
|
182
|
+
return value;
|
|
183
|
+
const first = value[0];
|
|
184
|
+
const last = value[value.length - 1];
|
|
185
|
+
if ((first === '"' && last === '"') || (first === "'" && last === "'")) {
|
|
186
|
+
return value.slice(1, -1);
|
|
187
|
+
}
|
|
188
|
+
return value;
|
|
189
|
+
}
|
|
190
|
+
//# sourceMappingURL=catalog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.js","sourceRoot":"","sources":["../../src/lib/catalog.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { SeedInputSchema } from '@praxis-framework/seed';
|
|
2
|
+
export function adaptFormToSeedInput(form) {
|
|
3
|
+
// Parse via the package schema directly. The CLI's Form already mirrors
|
|
4
|
+
// the SeedInput shape one-to-one (modulo the `path` and partial wrapping)
|
|
5
|
+
// so we can hand the relevant slice over and let zod do the strict
|
|
6
|
+
// validation in one place.
|
|
7
|
+
const candidate = {
|
|
8
|
+
organisation: form.organisation,
|
|
9
|
+
role_definition: form.role_definition,
|
|
10
|
+
voice_traits: form.voice_traits,
|
|
11
|
+
capabilities: form.capabilities,
|
|
12
|
+
inhibitions: form.inhibitions,
|
|
13
|
+
initial_verbs: form.initial_verbs,
|
|
14
|
+
tools: form.tools,
|
|
15
|
+
};
|
|
16
|
+
const parsed = SeedInputSchema.safeParse(candidate);
|
|
17
|
+
if (!parsed.success) {
|
|
18
|
+
return {
|
|
19
|
+
ok: false,
|
|
20
|
+
issues: parsed.error.issues.map((i) => ({
|
|
21
|
+
path: i.path.join('.') || '<root>',
|
|
22
|
+
message: i.message,
|
|
23
|
+
})),
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
return { ok: true, input: parsed.data };
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=seed-adapter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"seed-adapter.js","sourceRoot":"","sources":["../../src/lib/seed-adapter.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAkB,MAAM,wBAAwB,CAAC;AAmBzE,MAAM,UAAU,oBAAoB,CAAC,IAAU;IAC7C,wEAAwE;IACxE,0EAA0E;IAC1E,mEAAmE;IACnE,2BAA2B;IAC3B,MAAM,SAAS,GAAG;QAChB,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,eAAe,EAAE,IAAI,CAAC,eAAe;QACrC,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,YAAY,EAAE,IAAI,CAAC,YAAY;QAC/B,WAAW,EAAE,IAAI,CAAC,WAAW;QAC7B,aAAa,EAAE,IAAI,CAAC,aAAa;QACjC,KAAK,EAAE,IAAI,CAAC,KAAK;KAClB,CAAC;IAEF,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,MAAM,CAAC,OAAO,EAAE,CAAC;QACpB,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;gBACtC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,QAAQ;gBAClC,OAAO,EAAE,CAAC,CAAC,OAAO;aACnB,CAAC,CAAC;SACJ,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,IAAI,EAAE,CAAC;AAC1C,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Re-export the canonical trait library from `@praxis-framework/seed`. Both the CLI's
|
|
3
|
+
* voice flow (multi-select cloud) and the seeder (persona rendering) need
|
|
4
|
+
* the same authored list, and the seed package owns the source of truth so
|
|
5
|
+
* no copy can drift.
|
|
6
|
+
*
|
|
7
|
+
* A planned follow-up replaces the inline list in the seed package with a
|
|
8
|
+
* loader that reads `template/lib/traits.yaml`, mirroring the way
|
|
9
|
+
* `template/lib/tools.yaml` is loaded today. When that lands, this re-export
|
|
10
|
+
* stays in place and the CLI's import path doesn't change.
|
|
11
|
+
*/
|
|
12
|
+
export { TRAIT_LIBRARY, findTrait } from '@praxis-framework/seed';
|
|
13
|
+
//# sourceMappingURL=traits.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"traits.js","sourceRoot":"","sources":["../../src/lib/traits.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,aAAa,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC"}
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export const Organisation = z.object({
|
|
3
|
+
name: z.string().min(1),
|
|
4
|
+
website: z.string().optional(),
|
|
5
|
+
sector: z.string().optional(),
|
|
6
|
+
size: z.enum(['solo', 'small', 'mid', 'large', 'enterprise']).optional(),
|
|
7
|
+
description: z.string().optional(),
|
|
8
|
+
moats: z.string().optional(),
|
|
9
|
+
customer_profile: z.string().optional(),
|
|
10
|
+
});
|
|
11
|
+
export const RoleDefinition = z.object({
|
|
12
|
+
role_name: z.string().min(1),
|
|
13
|
+
working_title: z.string().optional(),
|
|
14
|
+
one_sentence_purpose: z.string().min(1),
|
|
15
|
+
day_to_day: z.string().optional(),
|
|
16
|
+
});
|
|
17
|
+
export const VoiceTrait = z.object({
|
|
18
|
+
/** Canonical name from the trait library (`cli/src/lib/traits.ts`). */
|
|
19
|
+
trait: z.string().min(1),
|
|
20
|
+
/** Free-text descriptors qualifying *how* the trait should manifest. */
|
|
21
|
+
qualifiers: z.array(z.string()).default([]),
|
|
22
|
+
});
|
|
23
|
+
export const InitialVerb = z.object({
|
|
24
|
+
/** Filename-shaped slug (lowercase letters, digits, hyphens; starts with a letter). */
|
|
25
|
+
slug: z.string().min(1),
|
|
26
|
+
/**
|
|
27
|
+
* Bullet-shaped body content for the verb file. 0-N free-text strings;
|
|
28
|
+
* each renders as a `- bullet` line in `verbs/<slug>.md`. An empty array
|
|
29
|
+
* is valid — the seeded file falls back to a bare heading + TODO marker.
|
|
30
|
+
*/
|
|
31
|
+
description: z.array(z.string()).default([]),
|
|
32
|
+
});
|
|
33
|
+
export const Form = z.object({
|
|
34
|
+
organisation: Organisation.partial(),
|
|
35
|
+
role_definition: RoleDefinition.partial(),
|
|
36
|
+
path: z.enum(['research', 'manual', 'unset']).default('unset'),
|
|
37
|
+
// Optional MCP capability names selected during the tool-selection step.
|
|
38
|
+
// Built-in capabilities (always_available in the catalog) are not stored
|
|
39
|
+
// here — they're implicit. v2 will extend each entry with per-MCP transport
|
|
40
|
+
// and auth overrides; v1 stores names only.
|
|
41
|
+
tools: z.array(z.string()).default([]),
|
|
42
|
+
// Voice & personality — canonical trait name (from the curated library at
|
|
43
|
+
// `cli/src/lib/traits.ts`) plus 0-N free-text qualifiers describing how the
|
|
44
|
+
// trait should manifest.
|
|
45
|
+
voice_traits: z.array(VoiceTrait).default([]),
|
|
46
|
+
// Action-shaped responsibilities for this role.
|
|
47
|
+
capabilities: z.array(z.string()).default([]),
|
|
48
|
+
// Hard "never do" rules, intentionally absolute.
|
|
49
|
+
inhibitions: z.array(z.string()).default([]),
|
|
50
|
+
// First verbs the role will run; slug is filename-shaped.
|
|
51
|
+
initial_verbs: z.array(InitialVerb).default([]),
|
|
52
|
+
});
|
|
53
|
+
export const emptyForm = () => ({
|
|
54
|
+
organisation: {},
|
|
55
|
+
role_definition: {},
|
|
56
|
+
path: 'unset',
|
|
57
|
+
tools: [],
|
|
58
|
+
voice_traits: [],
|
|
59
|
+
capabilities: [],
|
|
60
|
+
inhibitions: [],
|
|
61
|
+
initial_verbs: [],
|
|
62
|
+
});
|
|
63
|
+
//# sourceMappingURL=form.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"form.js","sourceRoot":"","sources":["../../src/state/form.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
export const STEPS = [
|
|
2
|
+
'welcome',
|
|
3
|
+
'organisation',
|
|
4
|
+
'role-definition',
|
|
5
|
+
'path-choice',
|
|
6
|
+
'tool-selection',
|
|
7
|
+
'voice',
|
|
8
|
+
'capabilities',
|
|
9
|
+
'inhibitions',
|
|
10
|
+
'initial-verbs',
|
|
11
|
+
'review',
|
|
12
|
+
'wrote',
|
|
13
|
+
];
|
|
14
|
+
export const firstStep = () => STEPS[0];
|
|
15
|
+
export const nextStep = (current) => {
|
|
16
|
+
const idx = STEPS.indexOf(current);
|
|
17
|
+
if (idx === -1 || idx === STEPS.length - 1)
|
|
18
|
+
return null;
|
|
19
|
+
return STEPS[idx + 1] ?? null;
|
|
20
|
+
};
|
|
21
|
+
export const previousStep = (current) => {
|
|
22
|
+
const idx = STEPS.indexOf(current);
|
|
23
|
+
if (idx <= 0)
|
|
24
|
+
return null;
|
|
25
|
+
return STEPS[idx - 1] ?? null;
|
|
26
|
+
};
|
|
27
|
+
export const isLastStep = (current) => current === STEPS[STEPS.length - 1];
|
|
28
|
+
//# sourceMappingURL=steps.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"steps.js","sourceRoot":"","sources":["../../src/state/steps.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,KAAK,GAAG;IACnB,SAAS;IACT,cAAc;IACd,iBAAiB;IACjB,aAAa;IACb,gBAAgB;IAChB,OAAO;IACP,cAAc;IACd,aAAa;IACb,eAAe;IACf,QAAQ;IACR,OAAO;CACC,CAAC;AAIX,MAAM,CAAC,MAAM,SAAS,GAAG,GAAS,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAE9C,MAAM,CAAC,MAAM,QAAQ,GAAG,CAAC,OAAa,EAAe,EAAE;IACrD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IACxD,OAAO,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,YAAY,GAAG,CAAC,OAAa,EAAe,EAAE;IACzD,MAAM,GAAG,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC;IACnC,IAAI,GAAG,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC1B,OAAO,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC;AAChC,CAAC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG,CAAC,OAAa,EAAW,EAAE,CACnD,OAAO,KAAK,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Box, Text } from 'ink';
|
|
3
|
+
import BigText from 'ink-big-text';
|
|
4
|
+
import Gradient from 'ink-gradient';
|
|
5
|
+
/** Full hero header — used once at welcome to establish presence. */
|
|
6
|
+
export const Header = () => (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsx(Gradient, { name: "atlas", children: _jsx(BigText, { text: "praxis", font: "tiny" }) }), _jsx(Text, { dimColor: true, children: " role-based agents that fit your business" })] }));
|
|
7
|
+
/**
|
|
8
|
+
* Compact persistent header — used on every step after welcome.
|
|
9
|
+
* Single-line brand mark with the same atlas gradient + an optional
|
|
10
|
+
* muted wayfinding string. Keeps the wizard branded without dominating
|
|
11
|
+
* the form below.
|
|
12
|
+
*/
|
|
13
|
+
export const CompactHeader = ({ context }) => (_jsxs(Box, { marginBottom: 1, children: [_jsx(Gradient, { name: "atlas", children: _jsx(Text, { children: "praxis" }) }), context && (_jsxs(Text, { dimColor: true, children: [' · ', context] }))] }));
|
|
14
|
+
//# sourceMappingURL=header.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"header.js","sourceRoot":"","sources":["../../src/ui/header.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,KAAK,CAAC;AAChC,OAAO,OAAO,MAAM,cAAc,CAAC;AACnC,OAAO,QAAQ,MAAM,cAAc,CAAC;AAEpC,qEAAqE;AACrE,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,EAAE,CAAC,CAC1B,MAAC,GAAG,IAAC,aAAa,EAAC,QAAQ,EAAC,YAAY,EAAE,CAAC,aACzC,KAAC,QAAQ,IAAC,IAAI,EAAC,OAAO,YACpB,KAAC,OAAO,IAAC,IAAI,EAAC,QAAQ,EAAC,IAAI,EAAC,MAAM,GAAG,GAC5B,EACX,KAAC,IAAI,IAAC,QAAQ,gEAAiD,IAC3D,CACP,CAAC;AAOF;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAAC,EAAE,OAAO,EAAsB,EAAE,EAAE,CAAC,CAChE,MAAC,GAAG,IAAC,YAAY,EAAE,CAAC,aAClB,KAAC,QAAQ,IAAC,IAAI,EAAC,OAAO,YACpB,KAAC,IAAI,yBAAc,GACV,EACV,OAAO,IAAI,CACV,MAAC,IAAI,IAAC,QAAQ,mBACX,KAAK,EACL,OAAO,IACH,CACR,IACG,CACP,CAAC"}
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pure state machine for {@link ListBuilder}. Extracted so the navigation /
|
|
3
|
+
* commit / focus rules can be unit-tested without rendering Ink, and so the
|
|
4
|
+
* component itself stays a thin presentational shell over `applyAction()`.
|
|
5
|
+
*
|
|
6
|
+
* The component owns three pieces of state that move together — `items`,
|
|
7
|
+
* `(rowIdx, fieldIdx)`, and the in-flight `draft` buffer — and a bug fixed
|
|
8
|
+
* here lived in the gap between them. The original useInput handler bound
|
|
9
|
+
* plain alphabetic keys (`j`, `k`, `d`) as navigation/delete shortcuts; those
|
|
10
|
+
* shortcuts also fired while a `TextInput` was focused, so a user typing
|
|
11
|
+
* `direct` would have the leading `d` racing with a row-clear. Centralising
|
|
12
|
+
* the rules into one transition function makes it obvious which keys mutate
|
|
13
|
+
* structure (tab/arrow/return/escape/empty-backspace) and which are purely
|
|
14
|
+
* for the text input to consume.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Build the initial state for a fresh ListBuilder mount. Always seeds at
|
|
18
|
+
* least one editable row so the operator has somewhere to start; the empty
|
|
19
|
+
* trailing row is dropped at finalise time.
|
|
20
|
+
*/
|
|
21
|
+
export function initialState(initial, config) {
|
|
22
|
+
const items = initial.length > 0 ? [...initial] : [config.empty()];
|
|
23
|
+
const draft = readDraft(items, 0, 0, config);
|
|
24
|
+
return { items, rowIdx: 0, fieldIdx: 0, draft };
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Apply a user-driven action to the state. Returns either the next state
|
|
28
|
+
* (`kind: 'state'`) or a finalise signal (`kind: 'finalise'`) carrying the
|
|
29
|
+
* trimmed items the caller should hand to `onNext`.
|
|
30
|
+
*
|
|
31
|
+
* The pure-function shape means tests can drive the same transitions the
|
|
32
|
+
* component does without setting up Ink, React, or input plumbing.
|
|
33
|
+
*/
|
|
34
|
+
export function applyAction(state, action, config) {
|
|
35
|
+
switch (action.type) {
|
|
36
|
+
case 'setDraft':
|
|
37
|
+
return { kind: 'state', state: { ...state, draft: action.value } };
|
|
38
|
+
case 'tab': {
|
|
39
|
+
if (config.fields.length === 0) {
|
|
40
|
+
return { kind: 'state', state };
|
|
41
|
+
}
|
|
42
|
+
const committed = commit(state, config);
|
|
43
|
+
const nextField = (state.fieldIdx + 1) % config.fields.length;
|
|
44
|
+
return {
|
|
45
|
+
kind: 'state',
|
|
46
|
+
state: refocus(committed, state.rowIdx, nextField, config),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
case 'down': {
|
|
50
|
+
const committed = commit(state, config);
|
|
51
|
+
if (committed.rowIdx < committed.items.length - 1) {
|
|
52
|
+
return {
|
|
53
|
+
kind: 'state',
|
|
54
|
+
state: refocus(committed, committed.rowIdx + 1, 0, config),
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
if (committed.items.length < config.max) {
|
|
58
|
+
const grown = {
|
|
59
|
+
...committed,
|
|
60
|
+
items: [...committed.items, config.empty()],
|
|
61
|
+
};
|
|
62
|
+
return {
|
|
63
|
+
kind: 'state',
|
|
64
|
+
state: refocus(grown, grown.items.length - 1, 0, config),
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
return { kind: 'state', state: committed };
|
|
68
|
+
}
|
|
69
|
+
case 'up': {
|
|
70
|
+
if (state.rowIdx === 0) {
|
|
71
|
+
return { kind: 'state', state };
|
|
72
|
+
}
|
|
73
|
+
const committed = commit(state, config);
|
|
74
|
+
return {
|
|
75
|
+
kind: 'state',
|
|
76
|
+
state: refocus(committed, committed.rowIdx - 1, 0, config),
|
|
77
|
+
};
|
|
78
|
+
}
|
|
79
|
+
case 'deleteRow': {
|
|
80
|
+
// If only one row remains, "delete" clears it back to empty rather
|
|
81
|
+
// than leaving the operator with zero rows to type into.
|
|
82
|
+
if (state.items.length <= 1) {
|
|
83
|
+
const cleared = [config.empty()];
|
|
84
|
+
return {
|
|
85
|
+
kind: 'state',
|
|
86
|
+
state: refocus({ ...state, items: cleared }, 0, 0, config),
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
const next = state.items.filter((_, i) => i !== state.rowIdx);
|
|
90
|
+
const nextRow = Math.min(state.rowIdx, next.length - 1);
|
|
91
|
+
return {
|
|
92
|
+
kind: 'state',
|
|
93
|
+
state: refocus({ ...state, items: next }, nextRow, 0, config),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
96
|
+
case 'submit': {
|
|
97
|
+
// Enter is "submit and add another" — commit the in-flight draft, then
|
|
98
|
+
// either advance to the next row (existing or freshly appended) or
|
|
99
|
+
// finalise. Finalise only fires when the operator hits enter on a row
|
|
100
|
+
// that is genuinely empty, mirroring "you've stopped adding things".
|
|
101
|
+
const committed = commit(state, config);
|
|
102
|
+
const focusedRow = committed.items[committed.rowIdx];
|
|
103
|
+
const focusedRowEmpty = focusedRow !== undefined &&
|
|
104
|
+
config.fields.every((f) => f.extract(focusedRow).trim().length === 0);
|
|
105
|
+
const isLast = committed.rowIdx === committed.items.length - 1;
|
|
106
|
+
// Empty trailing row — operator is signalling "I'm done". Drop the
|
|
107
|
+
// empty row and let the parent run its min/validate gates.
|
|
108
|
+
if (isLast && focusedRowEmpty) {
|
|
109
|
+
return {
|
|
110
|
+
kind: 'finalise',
|
|
111
|
+
items: trimEmptyRows(committed.items, config),
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
// Row has content — gate advancement on the row-level validator so the
|
|
115
|
+
// operator can't accumulate broken rows and only discover it on
|
|
116
|
+
// finalise. Without an advance, focus stays put and the row's inline
|
|
117
|
+
// error (rendered by the component using the same validator) surfaces.
|
|
118
|
+
if (focusedRow !== undefined && config.validate) {
|
|
119
|
+
const err = config.validate(focusedRow);
|
|
120
|
+
if (err !== null) {
|
|
121
|
+
return { kind: 'state', state: committed };
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
if (!isLast) {
|
|
125
|
+
// Same as ↓: commit current, move to existing next row.
|
|
126
|
+
return {
|
|
127
|
+
kind: 'state',
|
|
128
|
+
state: refocus(committed, committed.rowIdx + 1, 0, config),
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
// Last row, valid, has content. Try to grow; if at max, finalise so
|
|
132
|
+
// the operator isn't stuck pressing keys with no visible effect.
|
|
133
|
+
if (committed.items.length < config.max) {
|
|
134
|
+
const grown = {
|
|
135
|
+
...committed,
|
|
136
|
+
items: [...committed.items, config.empty()],
|
|
137
|
+
};
|
|
138
|
+
return {
|
|
139
|
+
kind: 'state',
|
|
140
|
+
state: refocus(grown, grown.items.length - 1, 0, config),
|
|
141
|
+
};
|
|
142
|
+
}
|
|
143
|
+
return { kind: 'finalise', items: trimEmptyRows(committed.items, config) };
|
|
144
|
+
}
|
|
145
|
+
default:
|
|
146
|
+
return { kind: 'state', state };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Strip rows where every field is blank — these are the "press enter to
|
|
151
|
+
* add another" affordance, not real entries.
|
|
152
|
+
*/
|
|
153
|
+
export function trimEmptyRows(items, config) {
|
|
154
|
+
return items.filter((item) => config.fields.some((f) => f.extract(item).trim().length > 0));
|
|
155
|
+
}
|
|
156
|
+
function readDraft(items, rowIdx, fieldIdx, config) {
|
|
157
|
+
const item = items[rowIdx];
|
|
158
|
+
const field = config.fields[fieldIdx];
|
|
159
|
+
return item && field ? field.extract(item) : '';
|
|
160
|
+
}
|
|
161
|
+
function commit(state, config) {
|
|
162
|
+
const item = state.items[state.rowIdx];
|
|
163
|
+
const field = config.fields[state.fieldIdx];
|
|
164
|
+
if (!item || !field)
|
|
165
|
+
return state;
|
|
166
|
+
const nextItem = field.apply(item, state.draft.trim());
|
|
167
|
+
const nextItems = [...state.items];
|
|
168
|
+
nextItems[state.rowIdx] = nextItem;
|
|
169
|
+
return { ...state, items: nextItems };
|
|
170
|
+
}
|
|
171
|
+
function refocus(state, rowIdx, fieldIdx, config) {
|
|
172
|
+
return {
|
|
173
|
+
...state,
|
|
174
|
+
rowIdx,
|
|
175
|
+
fieldIdx,
|
|
176
|
+
draft: readDraft(state.items, rowIdx, fieldIdx, config),
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
//# sourceMappingURL=list-builder-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-builder-state.js","sourceRoot":"","sources":["../../src/ui/list-builder-state.ts"],"names":[],"mappings":"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"}
|