@powerhousedao/ph-clint-cli 0.1.0-dev.4 → 0.1.0-dev.40
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/dist/cli.js +51 -12
- package/dist/codegen/actions.d.ts +42 -0
- package/dist/codegen/actions.js +372 -0
- package/dist/codegen/builders/agent-ts.d.ts +4 -4
- package/dist/codegen/builders/agent-ts.js +83 -2
- package/dist/codegen/builders/app-index-ts.d.ts +3 -10
- package/dist/codegen/builders/app-index-ts.js +10 -14
- package/dist/codegen/builders/cli-package-json.js +65 -8
- package/dist/codegen/builders/cli-ts.js +65 -24
- package/dist/codegen/builders/config-ts.js +11 -15
- package/dist/codegen/builders/demo-agent-ts.d.ts +8 -0
- package/dist/codegen/builders/demo-agent-ts.js +44 -0
- package/dist/codegen/builders/eslint-config-js.d.ts +1 -1
- package/dist/codegen/builders/eslint-config-js.js +7 -4
- package/dist/codegen/builders/framework-gen-ts.d.ts +4 -5
- package/dist/codegen/builders/framework-gen-ts.js +21 -18
- package/dist/codegen/builders/framework-ts.js +33 -7
- package/dist/codegen/builders/index.d.ts +10 -1
- package/dist/codegen/builders/index.js +30 -5
- package/dist/codegen/builders/manifest-json.d.ts +6 -0
- package/dist/codegen/builders/manifest-json.js +31 -0
- package/dist/codegen/builders/mastra-index-ts.d.ts +3 -0
- package/dist/codegen/builders/mastra-index-ts.js +47 -5
- package/dist/codegen/builders/publish-config-js.d.ts +8 -0
- package/dist/codegen/builders/publish-config-js.js +32 -0
- package/dist/codegen/builders/publish-config-ts.d.ts +8 -0
- package/dist/codegen/builders/publish-config-ts.js +32 -0
- package/dist/codegen/builders/readme-md.js +7 -6
- package/dist/codegen/builders/root-package-json.d.ts +3 -0
- package/dist/codegen/builders/root-package-json.js +26 -11
- package/dist/codegen/builders/smoke-test-ts.d.ts +2 -0
- package/dist/codegen/builders/smoke-test-ts.js +15 -0
- package/dist/codegen/generated.d.ts +17 -0
- package/dist/codegen/generated.js +49 -0
- package/dist/codegen/index.d.ts +3 -0
- package/dist/codegen/index.js +139 -14
- package/dist/codegen/scaffold.d.ts +31 -3
- package/dist/codegen/scaffold.js +114 -16
- package/dist/commands/clint-project-build.js +10 -27
- package/dist/commands/clint-project-init.d.ts +30 -6
- package/dist/commands/clint-project-init.js +45 -33
- package/dist/commands/clint-project-publish.d.ts +1 -0
- package/dist/commands/clint-project-publish.js +5 -3
- package/dist/commands/clint-project-regen.js +25 -1
- package/dist/commands/clint-skills-sync.d.ts +10 -0
- package/dist/commands/clint-skills-sync.js +56 -0
- package/dist/config.d.ts +3 -5
- package/dist/config.js +5 -7
- package/dist/framework.d.ts +5 -169
- package/dist/framework.gen.d.ts +1 -32
- package/dist/framework.js +0 -4
- package/{prompts/agent-profiles/AgentBase.md → dist/gen/agent-profiles/PhClintDevAgent.md} +1 -1
- package/dist/gen/skills/cli-setup/.cli-docs.md +135 -0
- package/dist/gen/skills/cli-setup/SKILL.md +125 -0
- package/dist/gen/skills/cli-setup/references/00.assess-cli-needs.md +53 -0
- package/dist/gen/skills/cli-setup/references/01.define-config-schema.md +78 -0
- package/dist/gen/skills/cli-setup/references/02.wire-cli.md +141 -0
- package/dist/gen/skills/cli-setup/references/03.add-entrypoint.md +128 -0
- package/dist/gen/skills/cli-setup/references/expected-outcome.md +3 -0
- package/dist/gen/skills/command-definition/.cli-docs.md +84 -0
- package/dist/gen/skills/command-definition/SKILL.md +99 -0
- package/dist/gen/skills/command-definition/references/00.assess-requirements.md +58 -0
- package/dist/gen/skills/command-definition/references/01.define-schema.md +72 -0
- package/dist/gen/skills/command-definition/references/02.implement-execute.md +118 -0
- package/dist/gen/skills/command-definition/references/03.add-prompting.md +54 -0
- package/dist/gen/skills/command-definition/references/expected-outcome.md +3 -0
- package/dist/gen/skills/service-definition/.cli-docs.md +214 -0
- package/dist/gen/skills/service-definition/SKILL.md +148 -0
- package/dist/gen/skills/service-definition/references/00.assess-service.md +69 -0
- package/dist/gen/skills/service-definition/references/01.define-service.md +166 -0
- package/dist/gen/skills/service-definition/references/02.add-preflight.md +132 -0
- package/dist/gen/skills/service-definition/references/03.add-project-scanner.md +82 -0
- package/dist/gen/skills/service-definition/references/04.wire-events.md +120 -0
- package/dist/gen/skills/service-definition/references/expected-outcome.md +3 -0
- package/dist/services/clint-project.js +21 -0
- package/dist/skills/sync.d.ts +40 -0
- package/dist/skills/sync.js +119 -0
- package/dist/spec/ensure-document.d.ts +17 -0
- package/dist/spec/ensure-document.js +62 -0
- package/dist/spec/from-document.d.ts +4 -1
- package/dist/spec/from-document.js +18 -8
- package/dist/spec/types.d.ts +85 -6
- package/dist/spec/types.js +90 -23
- package/dist/triggers/publish-trigger.d.ts +10 -0
- package/dist/triggers/publish-trigger.js +169 -0
- package/dist/triggers/spec-change.d.ts +5 -34
- package/dist/triggers/spec-change.js +130 -102
- package/package.json +7 -7
- package/prompts/skills-ext/.gitkeep +0 -0
- package/prompts/skills-tpl/.gitkeep +0 -0
|
@@ -17,9 +17,26 @@ import { buildMastraIndexTs } from './mastra-index-ts.js';
|
|
|
17
17
|
import { buildBuildSkillsScript } from './build-skills-ts.js';
|
|
18
18
|
import { buildAgentBaseMd } from './agent-base-md.js';
|
|
19
19
|
import { buildAgentTs } from './agent-ts.js';
|
|
20
|
+
import { buildDemoAgentTs } from './demo-agent-ts.js';
|
|
20
21
|
import { buildFrameworkGenTs } from './framework-gen-ts.js';
|
|
21
22
|
import { buildFrameworkTs } from './framework-ts.js';
|
|
23
|
+
import { buildManifestJson } from './manifest-json.js';
|
|
24
|
+
import { buildSmokeTestTs } from './smoke-test-ts.js';
|
|
25
|
+
/**
|
|
26
|
+
* Generate dynamic file builders for agent profile markdown files.
|
|
27
|
+
* One file per profile in `prompts/agent-profiles/{id}.md`.
|
|
28
|
+
*/
|
|
29
|
+
export function getProfileFileBuilders(spec) {
|
|
30
|
+
const { mastra } = spec.features;
|
|
31
|
+
if (!mastra.enabled || mastra.profiles.length === 0)
|
|
32
|
+
return [];
|
|
33
|
+
return mastra.profiles.map((profile) => ({
|
|
34
|
+
relativePath: `prompts/agent-profiles/${profile.id}.md`,
|
|
35
|
+
build: () => profile.content + '\n',
|
|
36
|
+
}));
|
|
37
|
+
}
|
|
22
38
|
export const CLI_FILE_BUILDERS = [
|
|
39
|
+
{ relativePath: 'powerhouse.manifest.json', build: buildManifestJson },
|
|
23
40
|
{ relativePath: 'package.json', build: buildCliPackageJson },
|
|
24
41
|
{ relativePath: 'tsconfig.json', build: () => buildTsconfigJson() },
|
|
25
42
|
{ relativePath: 'jest.config.js', build: () => buildJestConfigJs() },
|
|
@@ -28,17 +45,24 @@ export const CLI_FILE_BUILDERS = [
|
|
|
28
45
|
{ relativePath: 'src/main.ts', build: () => buildMainTs() },
|
|
29
46
|
{ relativePath: 'src/cli.ts', build: buildCliTs },
|
|
30
47
|
{ relativePath: 'src/config.ts', build: buildConfigTs },
|
|
31
|
-
// User-owned
|
|
32
|
-
{ relativePath: 'src/framework.ts', build: buildFrameworkTs
|
|
48
|
+
// User-owned outside markers; generated config/secrets inside markers.
|
|
49
|
+
{ relativePath: 'src/framework.ts', build: buildFrameworkTs },
|
|
33
50
|
// Machine-owned; regenerated on every run. Null when no document types.
|
|
34
51
|
{ relativePath: 'src/framework.gen.ts', build: buildFrameworkGenTs },
|
|
35
52
|
{ relativePath: 'src/mastra/index.ts', build: buildMastraIndexTs },
|
|
36
53
|
{ relativePath: 'scripts/build-skills.ts', build: () => buildBuildSkillsScript() },
|
|
37
|
-
{
|
|
54
|
+
{
|
|
55
|
+
relativePath: 'prompts/agent-profiles/AgentBase.md',
|
|
56
|
+
build: (spec) => (spec.features.mastra.profiles.length > 0 ? null : buildAgentBaseMd(spec)),
|
|
57
|
+
},
|
|
38
58
|
{
|
|
39
59
|
relativePath: 'src/agents/agent.ts',
|
|
40
60
|
build: (spec) => (spec.features.mastra.enabled ? buildAgentTs(spec) : null),
|
|
41
61
|
},
|
|
62
|
+
{
|
|
63
|
+
relativePath: 'src/agents/demo-agent.ts',
|
|
64
|
+
build: buildDemoAgentTs,
|
|
65
|
+
},
|
|
42
66
|
// Gitkeep placeholders so directories are tracked in git when otherwise empty.
|
|
43
67
|
{ relativePath: 'src/commands/.gitkeep', build: () => '' },
|
|
44
68
|
{ relativePath: 'src/services/.gitkeep', build: () => '' },
|
|
@@ -52,9 +76,10 @@ export const CLI_FILE_BUILDERS = [
|
|
|
52
76
|
},
|
|
53
77
|
{ relativePath: 'prompts/skills-tpl/.gitkeep', build: () => '' },
|
|
54
78
|
{ relativePath: 'prompts/skills-ext/.gitkeep', build: () => '' },
|
|
55
|
-
{ relativePath: 'tests
|
|
79
|
+
{ relativePath: 'tests/smoke.test.ts', build: buildSmokeTestTs, initOnly: true },
|
|
56
80
|
];
|
|
57
|
-
export { buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildFrameworkGenTs, buildFrameworkTs, };
|
|
81
|
+
export { buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildDemoAgentTs, buildFrameworkGenTs, buildFrameworkTs, buildManifestJson, buildSmokeTestTs, };
|
|
58
82
|
export { buildRootPackageJson } from './root-package-json.js';
|
|
83
|
+
export { buildPublishConfigJs } from './publish-config-js.js';
|
|
59
84
|
export { buildReadme } from './readme-md.js';
|
|
60
85
|
export { buildAppIndexTs } from './app-index-ts.js';
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `powerhouse.manifest.json` — a machine-readable manifest describing
|
|
3
|
+
* the CLI project's capabilities for service discovery and deployment.
|
|
4
|
+
*/
|
|
5
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
6
|
+
export declare function buildManifestJson(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `powerhouse.manifest.json` — a machine-readable manifest describing
|
|
3
|
+
* the CLI project's capabilities for service discovery and deployment.
|
|
4
|
+
*/
|
|
5
|
+
import { getBinName, getAppPackageName, phAtLeast, } from '../../spec/types.js';
|
|
6
|
+
export function buildManifestJson(spec) {
|
|
7
|
+
const { mastra, powerhouse } = spec.features;
|
|
8
|
+
const agent = mastra.enabled
|
|
9
|
+
? {
|
|
10
|
+
id: mastra.agentId ?? spec.name,
|
|
11
|
+
name: mastra.agentName ?? spec.name,
|
|
12
|
+
description: mastra.agentDescription ?? null,
|
|
13
|
+
image: mastra.agentImage ?? null,
|
|
14
|
+
models: mastra.models.map((m) => ({ id: m.id, default: m.isDefault })),
|
|
15
|
+
}
|
|
16
|
+
: false;
|
|
17
|
+
const ph = phAtLeast(powerhouse, 'Reactor')
|
|
18
|
+
? {
|
|
19
|
+
support: powerhouse,
|
|
20
|
+
package: getAppPackageName(spec),
|
|
21
|
+
}
|
|
22
|
+
: false;
|
|
23
|
+
const manifest = {
|
|
24
|
+
type: 'clint-project',
|
|
25
|
+
features: { agent, powerhouse: ph },
|
|
26
|
+
serviceCommand: getBinName(spec),
|
|
27
|
+
serviceAnnouncement: spec.deployment.serviceAnnouncement,
|
|
28
|
+
supportedResources: spec.deployment.supportedResources,
|
|
29
|
+
};
|
|
30
|
+
return JSON.stringify(manifest, null, 2) + '\n';
|
|
31
|
+
}
|
|
@@ -3,6 +3,9 @@
|
|
|
3
3
|
*
|
|
4
4
|
* When Mastra is off, emit a no-op placeholder so the directory still exists
|
|
5
5
|
* and `mastra dev` fails predictably rather than importing partial code.
|
|
6
|
+
*
|
|
7
|
+
* When Mastra is on with full agent config, bootstrap the CLI and re-export
|
|
8
|
+
* the configured Mastra Agent via `cli.bootstrap()`.
|
|
6
9
|
*/
|
|
7
10
|
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
8
11
|
export declare function buildMastraIndexTs(spec: ClintProjectSpec): string;
|
|
@@ -1,28 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Derive the `{PROVIDER}_API_KEY` env var name from a provider prefix
|
|
3
|
+
* (e.g. `anthropic` → `ANTHROPIC_API_KEY`).
|
|
4
|
+
*/
|
|
5
|
+
function getApiKeyEnvVar(provider) {
|
|
6
|
+
return `${provider.toUpperCase()}_API_KEY`;
|
|
7
|
+
}
|
|
1
8
|
export function buildMastraIndexTs(spec) {
|
|
2
9
|
const { mastra } = spec.features;
|
|
3
10
|
if (!mastra.enabled) {
|
|
4
11
|
return [
|
|
12
|
+
'// @clint:begin mastra-index',
|
|
5
13
|
'/**',
|
|
6
14
|
' * Mastra Studio entry point — placeholder. Enable the `mastra` feature to',
|
|
7
15
|
' * populate this file. Until then `mastra:*` scripts are effectively no-ops.',
|
|
8
16
|
' */',
|
|
9
|
-
'// @clint:begin mastra-index',
|
|
10
17
|
'export {};',
|
|
11
18
|
'// @clint:end mastra-index',
|
|
12
19
|
'',
|
|
13
20
|
].join('\n');
|
|
14
21
|
}
|
|
15
|
-
//
|
|
16
|
-
|
|
17
|
-
|
|
22
|
+
// Full agent config available — emit bootstrap-based Mastra instance
|
|
23
|
+
if (mastra.agentId && mastra.models.length > 0) {
|
|
24
|
+
const providers = [...new Set(mastra.models.map(m => m.id.split(/[:/]/)[0]))];
|
|
25
|
+
const lines = [
|
|
26
|
+
'// @clint:begin mastra-index',
|
|
27
|
+
'/**',
|
|
28
|
+
' * Mastra Studio entry point for `mastra dev` / `mastra build` / `mastra start`.',
|
|
29
|
+
' *',
|
|
30
|
+
' * Bootstraps the CLI to get the configured agent, then exports a Mastra',
|
|
31
|
+
' * instance for Studio integration.',
|
|
32
|
+
' */',
|
|
33
|
+
"import { Mastra } from '@mastra/core/mastra';",
|
|
34
|
+
"import type { Agent } from '@mastra/core/agent';",
|
|
35
|
+
"import path from 'node:path';",
|
|
36
|
+
"import { cli } from '../cli.js';",
|
|
37
|
+
"import { CLI_ROOT } from '../config.js';",
|
|
38
|
+
'',
|
|
39
|
+
"// Under `mastra dev`, CLI_ROOT points to .mastra/ (bundler output).",
|
|
40
|
+
'// The actual project root is its parent.',
|
|
41
|
+
"const projectRoot = path.basename(CLI_ROOT) === '.mastra'",
|
|
42
|
+
' ? path.dirname(CLI_ROOT)',
|
|
43
|
+
' : CLI_ROOT;',
|
|
44
|
+
'',
|
|
45
|
+
'const rt = await cli.bootstrap({ workdir: projectRoot });',
|
|
46
|
+
'',
|
|
47
|
+
];
|
|
48
|
+
// API key env bridge for Studio
|
|
49
|
+
lines.push(`// Workaround: Mastra Studio checks process.env for API keys directly.`, `// Bridge the ph-clint resolved keys so Studio's provider detection works.`);
|
|
50
|
+
for (const provider of providers) {
|
|
51
|
+
const field = `${provider}ApiKey`;
|
|
52
|
+
const envVar = getApiKeyEnvVar(provider);
|
|
53
|
+
lines.push(`{`, ` const key = rt.config.${field} as string | undefined;`, ` if (key && !process.env.${envVar}) process.env.${envVar} = key;`, `}`);
|
|
54
|
+
}
|
|
55
|
+
lines.push('');
|
|
56
|
+
lines.push('const mastraAgent = await rt.mastraAgent as Agent | undefined;', '', 'export const mastra = new Mastra({', ' agents: mastraAgent ? { [mastraAgent.id]: mastraAgent } : {},', '});', '// @clint:end mastra-index', '');
|
|
57
|
+
return lines.join('\n');
|
|
58
|
+
}
|
|
59
|
+
// Mastra enabled but no full agent config yet — placeholder
|
|
18
60
|
return [
|
|
61
|
+
'// @clint:begin mastra-index',
|
|
19
62
|
'/**',
|
|
20
63
|
' * Mastra Studio entry point for `mastra dev` / `mastra build` / `mastra start`.',
|
|
21
64
|
' *',
|
|
22
65
|
" * Re-export a configured `@mastra/core` Mastra instance from here once you",
|
|
23
66
|
" * replace the demo createAgent shim with a real Mastra Agent.",
|
|
24
67
|
' */',
|
|
25
|
-
'// @clint:begin mastra-index',
|
|
26
68
|
'export {};',
|
|
27
69
|
'// @clint:end mastra-index',
|
|
28
70
|
'',
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the root `publish.config.js`.
|
|
3
|
+
*
|
|
4
|
+
* Split-layout: a lockstep group with both app and cli packages.
|
|
5
|
+
* Single-layout: a single-package group at `.`.
|
|
6
|
+
*/
|
|
7
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
8
|
+
export declare function buildPublishConfigJs(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the root `publish.config.js`.
|
|
3
|
+
*
|
|
4
|
+
* Split-layout: a lockstep group with both app and cli packages.
|
|
5
|
+
* Single-layout: a single-package group at `.`.
|
|
6
|
+
*/
|
|
7
|
+
import { phAtLeast } from '../../spec/types.js';
|
|
8
|
+
export function buildPublishConfigJs(spec) {
|
|
9
|
+
const split = phAtLeast(spec.features.powerhouse, 'Reactor');
|
|
10
|
+
// The publish pipeline appends the prerelease suffix (e.g. -dev.0), so we
|
|
11
|
+
// only store the base semver (M.m.p) here.
|
|
12
|
+
const baseVersion = spec.version.replace(/-.*$/, '');
|
|
13
|
+
const packages = split
|
|
14
|
+
? `[
|
|
15
|
+
{ path: '${spec.name}-app', category: 'app' },
|
|
16
|
+
{ path: '${spec.name}-cli', category: 'cli' },
|
|
17
|
+
]`
|
|
18
|
+
: `[
|
|
19
|
+
{ path: '.', category: 'cli' },
|
|
20
|
+
]`;
|
|
21
|
+
return `// Publish config — loaded by ph-clint's publish pipeline.
|
|
22
|
+
// definePublishConfig is an identity function; a plain export is equivalent.
|
|
23
|
+
export default {
|
|
24
|
+
groups: {
|
|
25
|
+
'${spec.name}': {
|
|
26
|
+
version: '${baseVersion}',
|
|
27
|
+
packages: ${packages},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the root `publish.config.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Split-layout: a lockstep group with both app and cli packages.
|
|
5
|
+
* Single-layout: a single-package group at `.`.
|
|
6
|
+
*/
|
|
7
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
8
|
+
export declare function buildPublishConfigTs(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds the root `publish.config.ts`.
|
|
3
|
+
*
|
|
4
|
+
* Split-layout: a lockstep group with both app and cli packages.
|
|
5
|
+
* Single-layout: a single-package group at `.`.
|
|
6
|
+
*/
|
|
7
|
+
import { phAtLeast } from '../../spec/types.js';
|
|
8
|
+
export function buildPublishConfigTs(spec) {
|
|
9
|
+
const split = phAtLeast(spec.features.powerhouse, 'Reactor');
|
|
10
|
+
// The publish pipeline appends the prerelease suffix (e.g. -dev.0), so we
|
|
11
|
+
// only store the base semver (M.m.p) here.
|
|
12
|
+
const baseVersion = spec.version.replace(/-.*$/, '');
|
|
13
|
+
const packages = split
|
|
14
|
+
? `[
|
|
15
|
+
{ path: '${spec.name}-app', category: 'app' },
|
|
16
|
+
{ path: '${spec.name}-cli', category: 'cli' },
|
|
17
|
+
]`
|
|
18
|
+
: `[
|
|
19
|
+
{ path: '.', category: 'cli' },
|
|
20
|
+
]`;
|
|
21
|
+
return `// Publish config — loaded by ph-clint's publish pipeline.
|
|
22
|
+
// definePublishConfig is an identity function; a plain export is equivalent.
|
|
23
|
+
export default {
|
|
24
|
+
groups: {
|
|
25
|
+
'${spec.name}': {
|
|
26
|
+
version: '${baseVersion}',
|
|
27
|
+
packages: ${packages},
|
|
28
|
+
},
|
|
29
|
+
},
|
|
30
|
+
};
|
|
31
|
+
`;
|
|
32
|
+
}
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Builds the project README for a freshly-generated ph-clint project.
|
|
3
3
|
*/
|
|
4
|
-
import { getPackageName, } from '../../spec/types.js';
|
|
4
|
+
import { getPackageName, phAtLeast, } from '../../spec/types.js';
|
|
5
5
|
export function buildReadme(spec) {
|
|
6
6
|
const { mastra, routine, powerhouse } = spec.features;
|
|
7
|
+
const ph = powerhouse;
|
|
7
8
|
const title = getPackageName(spec);
|
|
8
9
|
const lines = [];
|
|
9
10
|
lines.push(`# ${title}`);
|
|
@@ -19,10 +20,10 @@ export function buildReadme(spec) {
|
|
|
19
20
|
lines.push('');
|
|
20
21
|
lines.push('## Enabled features');
|
|
21
22
|
lines.push('');
|
|
22
|
-
lines.push(`- **Powerhouse**: ${
|
|
23
|
-
if (
|
|
24
|
-
lines.push(` - Switchboard: ${
|
|
25
|
-
lines.push(` - Connect: ${
|
|
23
|
+
lines.push(`- **Powerhouse**: ${ph !== 'Disabled' ? `on (${ph})` : 'off'}`);
|
|
24
|
+
if (phAtLeast(ph, 'Reactor')) {
|
|
25
|
+
lines.push(` - Switchboard: ${phAtLeast(ph, 'Switchboard') ? 'on' : 'off'}`);
|
|
26
|
+
lines.push(` - Connect: ${phAtLeast(ph, 'Connect') ? 'on' : 'off'}`);
|
|
26
27
|
}
|
|
27
28
|
lines.push(`- **Mastra agent**: ${mastra.enabled ? 'on' : 'off'}`);
|
|
28
29
|
lines.push(`- **Routine loop**: ${routine.enabled ? 'on' : 'off'}`);
|
|
@@ -32,7 +33,7 @@ export function buildReadme(spec) {
|
|
|
32
33
|
lines.push('Toggle features or update metadata in `.ph/ph-clint-cli/project-spec.json`,');
|
|
33
34
|
lines.push('then re-run `ph-clint clint-project-regen` to regenerate.');
|
|
34
35
|
lines.push('');
|
|
35
|
-
if (
|
|
36
|
+
if (phAtLeast(ph, 'Reactor')) {
|
|
36
37
|
lines.push('## Split layout');
|
|
37
38
|
lines.push('');
|
|
38
39
|
lines.push(`This project is split into \`${spec.name}-cli/\` (the CLI) and \`${spec.name}-app/\` (the Powerhouse reactor package).`);
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
* Builds the *root* `package.json` for split-layout projects (Powerhouse
|
|
3
3
|
* enabled). A plain passthrough — deliberately no pnpm workspaces because
|
|
4
4
|
* they interfere with `{name}-app`'s own `pnpm build`.
|
|
5
|
+
*
|
|
6
|
+
* Uses `pnpm --prefix <dir>` for all orchestration scripts — no cwd mutation.
|
|
7
|
+
* Build order: app first, then cli (cli depends on app via `file:` dep).
|
|
5
8
|
*/
|
|
6
9
|
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
7
10
|
export declare function buildRootPackageJson(spec: ClintProjectSpec): string;
|
|
@@ -2,26 +2,41 @@
|
|
|
2
2
|
* Builds the *root* `package.json` for split-layout projects (Powerhouse
|
|
3
3
|
* enabled). A plain passthrough — deliberately no pnpm workspaces because
|
|
4
4
|
* they interfere with `{name}-app`'s own `pnpm build`.
|
|
5
|
+
*
|
|
6
|
+
* Uses `pnpm --prefix <dir>` for all orchestration scripts — no cwd mutation.
|
|
7
|
+
* Build order: app first, then cli (cli depends on app via `file:` dep).
|
|
5
8
|
*/
|
|
6
|
-
import { getPackageName, } from '../../spec/types.js';
|
|
9
|
+
import { getPackageName, phAtLeast, } from '../../spec/types.js';
|
|
7
10
|
export function buildRootPackageJson(spec) {
|
|
8
11
|
const cli = `${spec.name}-cli`;
|
|
9
12
|
const app = `${spec.name}-app`;
|
|
13
|
+
const prefix = (dir, cmd) => `pnpm --prefix ${dir} ${cmd}`;
|
|
14
|
+
const both = (cmd) => `${prefix(app, cmd)} && ${prefix(cli, cmd)}`;
|
|
15
|
+
const connectEnabled = phAtLeast(spec.features.powerhouse, 'Connect');
|
|
16
|
+
const buildScript = connectEnabled
|
|
17
|
+
? `${prefix(app, 'build')} && ${prefix(app, 'connect:build')} && ${prefix(cli, 'build')}`
|
|
18
|
+
: both('build');
|
|
19
|
+
const scripts = {
|
|
20
|
+
install: both('install'),
|
|
21
|
+
build: buildScript,
|
|
22
|
+
test: both('test'),
|
|
23
|
+
dev: prefix(cli, 'dev'),
|
|
24
|
+
start: prefix(cli, 'start'),
|
|
25
|
+
lint: both('lint'),
|
|
26
|
+
'publish:dev': `${prefix(cli, 'exec ph-publish')} dev -c ../publish.config.js`,
|
|
27
|
+
'publish:staging': `${prefix(cli, 'exec ph-publish')} staging -c ../publish.config.js`,
|
|
28
|
+
'publish:production': `${prefix(cli, 'exec ph-publish')} production -c ../publish.config.js`,
|
|
29
|
+
};
|
|
30
|
+
if (spec.deployment.serviceAnnouncement) {
|
|
31
|
+
scripts['test-service-registry'] = prefix(cli, 'test-service-registry');
|
|
32
|
+
}
|
|
10
33
|
const pkg = {
|
|
11
34
|
name: getPackageName(spec),
|
|
12
35
|
version: spec.version,
|
|
13
36
|
private: true,
|
|
37
|
+
type: 'module',
|
|
14
38
|
...(spec.description ? { description: spec.description } : {}),
|
|
15
|
-
scripts
|
|
16
|
-
install: `cd ${app} && pnpm install && cd ../${cli} && pnpm install`,
|
|
17
|
-
build: `cd ${app} && pnpm build && cd ../${cli} && pnpm build`,
|
|
18
|
-
dev: `cd ${cli} && pnpm dev`,
|
|
19
|
-
start: `cd ${cli} && pnpm start`,
|
|
20
|
-
test: `cd ${app} && pnpm test && cd ../${cli} && pnpm test`,
|
|
21
|
-
lint: `cd ${cli} && pnpm lint`,
|
|
22
|
-
'app:dev': `cd ${app} && pnpm dev`,
|
|
23
|
-
'cli:dev': `cd ${cli} && pnpm dev`,
|
|
24
|
-
},
|
|
39
|
+
scripts,
|
|
25
40
|
};
|
|
26
41
|
return JSON.stringify(pkg, null, 2) + '\n';
|
|
27
42
|
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { getBinName } from '../../spec/types.js';
|
|
2
|
+
export function buildSmokeTestTs(spec) {
|
|
3
|
+
const bin = getBinName(spec);
|
|
4
|
+
return [
|
|
5
|
+
`import { describe, it, expect } from '@jest/globals';`,
|
|
6
|
+
``,
|
|
7
|
+
`describe('${bin}', () => {`,
|
|
8
|
+
` it('loads without error', async () => {`,
|
|
9
|
+
` const { cli } = await import('../src/cli.js');`,
|
|
10
|
+
` expect(cli).toBeDefined();`,
|
|
11
|
+
` });`,
|
|
12
|
+
`});`,
|
|
13
|
+
``,
|
|
14
|
+
].join('\n');
|
|
15
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type ClintProjectSpec } from '../spec/types.js';
|
|
2
|
+
export interface GeneratedState {
|
|
3
|
+
name: string;
|
|
4
|
+
scope: string | undefined;
|
|
5
|
+
cliFolderName: string;
|
|
6
|
+
appFolderName: string;
|
|
7
|
+
/** True once `ph init` has run successfully in the app dir. */
|
|
8
|
+
appInitialized: boolean;
|
|
9
|
+
}
|
|
10
|
+
export declare function getGeneratedPath(targetDir: string): string;
|
|
11
|
+
export declare function readGeneratedState(targetDir: string): Promise<GeneratedState | null>;
|
|
12
|
+
export declare function writeGeneratedState(targetDir: string, state: GeneratedState): Promise<void>;
|
|
13
|
+
/**
|
|
14
|
+
* Derive a `GeneratedState` from a spec. The `appInitialized` flag must be
|
|
15
|
+
* supplied by the caller (it depends on filesystem state, not the spec).
|
|
16
|
+
*/
|
|
17
|
+
export declare function generatedStateFromSpec(spec: ClintProjectSpec, appInitialized: boolean): GeneratedState;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Tracks the derived state from the last successful code generation.
|
|
3
|
+
*
|
|
4
|
+
* Stored at `{targetDir}/.ph/ph-clint-cli/generated.json`. Used to detect
|
|
5
|
+
* folder renames (name/scope changes) and re-apply patches that depend on
|
|
6
|
+
* the project identity.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'node:fs/promises';
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { getAppFolderName, getCliFolderName, } from '../spec/types.js';
|
|
11
|
+
const GEN_DIR = path.join('.ph', 'ph-clint-cli');
|
|
12
|
+
const GEN_FILE = 'generated.json';
|
|
13
|
+
export function getGeneratedPath(targetDir) {
|
|
14
|
+
return path.join(targetDir, GEN_DIR, GEN_FILE);
|
|
15
|
+
}
|
|
16
|
+
export async function readGeneratedState(targetDir) {
|
|
17
|
+
try {
|
|
18
|
+
const raw = await fs.readFile(getGeneratedPath(targetDir), 'utf8');
|
|
19
|
+
return JSON.parse(raw);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (err &&
|
|
23
|
+
typeof err === 'object' &&
|
|
24
|
+
'code' in err &&
|
|
25
|
+
err.code === 'ENOENT') {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
throw err;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export async function writeGeneratedState(targetDir, state) {
|
|
32
|
+
const file = getGeneratedPath(targetDir);
|
|
33
|
+
await fs.mkdir(path.dirname(file), { recursive: true });
|
|
34
|
+
await fs.writeFile(file, JSON.stringify(state, null, 2) + '\n', 'utf8');
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Derive a `GeneratedState` from a spec. The `appInitialized` flag must be
|
|
38
|
+
* supplied by the caller (it depends on filesystem state, not the spec).
|
|
39
|
+
*/
|
|
40
|
+
export function generatedStateFromSpec(spec, appInitialized) {
|
|
41
|
+
const split = spec.features.powerhouse !== 'Disabled';
|
|
42
|
+
return {
|
|
43
|
+
name: spec.name,
|
|
44
|
+
scope: spec.scope,
|
|
45
|
+
cliFolderName: split ? getCliFolderName(spec) : '',
|
|
46
|
+
appFolderName: split ? getAppFolderName(spec) : '',
|
|
47
|
+
appInitialized,
|
|
48
|
+
};
|
|
49
|
+
}
|
package/dist/codegen/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type ClintProjectSpec } from '../spec/types.js';
|
|
2
|
+
import { type PostGenAction } from './actions.js';
|
|
2
3
|
export type GenerateMode = 'create' | 'update' | 'auto';
|
|
3
4
|
export interface GenerateProjectOptions {
|
|
4
5
|
/** Absolute path to the project root. */
|
|
@@ -32,6 +33,8 @@ export interface GenerateProjectResult {
|
|
|
32
33
|
migrated: boolean;
|
|
33
34
|
cliDir: string;
|
|
34
35
|
appDir: string | null;
|
|
36
|
+
/** Pending post-generation actions derived from what changed. */
|
|
37
|
+
pendingActions: PostGenAction[];
|
|
35
38
|
}
|
|
36
39
|
/**
|
|
37
40
|
* Generate / reconcile a project at `targetDir` from the given spec.
|