@powerhousedao/ph-clint-cli 0.1.0-dev.3 → 0.1.0-dev.31
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 +31 -12
- 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 +48 -8
- package/dist/codegen/builders/cli-ts.js +63 -22
- 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/framework-gen-ts.d.ts +4 -5
- package/dist/codegen/builders/framework-gen-ts.js +22 -19
- package/dist/codegen/builders/framework-ts.js +33 -7
- package/dist/codegen/builders/index.d.ts +9 -1
- package/dist/codegen/builders/index.js +28 -4
- 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-ts.d.ts +6 -0
- package/dist/codegen/builders/publish-config-ts.js +21 -0
- package/dist/codegen/builders/readme-md.js +8 -7
- package/dist/codegen/builders/root-package-json.d.ts +3 -0
- package/dist/codegen/builders/root-package-json.js +24 -11
- package/dist/codegen/index.js +26 -12
- package/dist/codegen/scaffold.d.ts +21 -3
- package/dist/codegen/scaffold.js +90 -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 -9
- 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 +2 -2
- 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.gen.js +1 -1
- 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/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 +175 -99
- package/package.json +7 -7
- package/prompts/skills-ext/.gitkeep +0 -0
- package/prompts/skills-tpl/.gitkeep +0 -0
package/dist/codegen/scaffold.js
CHANGED
|
@@ -7,7 +7,26 @@
|
|
|
7
7
|
*/
|
|
8
8
|
import fs from 'node:fs/promises';
|
|
9
9
|
import path from 'node:path';
|
|
10
|
-
import {
|
|
10
|
+
import { execFileSync } from 'node:child_process';
|
|
11
|
+
import { hasCommandOnPath } from './exec.js';
|
|
12
|
+
/**
|
|
13
|
+
* Detect the installed `ph` CLI version by parsing `ph --version` output.
|
|
14
|
+
* Returns the version string (e.g. '6.0.0-dev.194') or undefined if
|
|
15
|
+
* detection fails.
|
|
16
|
+
*/
|
|
17
|
+
export function getPhVersion(binName) {
|
|
18
|
+
try {
|
|
19
|
+
const output = execFileSync(binName, ['--version'], {
|
|
20
|
+
encoding: 'utf-8',
|
|
21
|
+
timeout: 5_000,
|
|
22
|
+
});
|
|
23
|
+
const match = output.match(/PH CMD version:\s*(\S+)/);
|
|
24
|
+
return match?.[1];
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
11
30
|
export async function runPhInit(options) {
|
|
12
31
|
const log = options.log ?? (() => { });
|
|
13
32
|
const binName = options.binName ?? 'ph';
|
|
@@ -17,23 +36,65 @@ export async function runPhInit(options) {
|
|
|
17
36
|
`Install @powerhousedao/ph-cli and re-run manually inside ${appFolder}/.`);
|
|
18
37
|
return { ran: false, reason: 'ph-not-on-path' };
|
|
19
38
|
}
|
|
39
|
+
// Pin ph init to the same version as the installed ph CLI, so the
|
|
40
|
+
// generated app uses matching Powerhouse packages.
|
|
41
|
+
const phVersion = options.phVersion ?? getPhVersion(binName);
|
|
42
|
+
const tags = ['dev', 'staging', 'latest'];
|
|
43
|
+
const versionArgs = phVersion
|
|
44
|
+
? tags.includes(phVersion)
|
|
45
|
+
? [`--${phVersion}`]
|
|
46
|
+
: ['--version', phVersion]
|
|
47
|
+
: ['--dev']; // fallback if detection fails
|
|
20
48
|
// `ph init {name}` creates a fresh directory beside the cwd. Our generator
|
|
21
49
|
// placed a `.gitkeep` + README.md placeholder there; clear it out so
|
|
22
50
|
// ph init has a blank slate to work with.
|
|
23
51
|
await fs.rm(options.appDir, { recursive: true, force: true });
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
'
|
|
29
|
-
|
|
30
|
-
|
|
52
|
+
const args = ['init', appFolder, ...versionArgs, '--pnpm'];
|
|
53
|
+
log(`Running \`${binName} init ${appFolder}\` (version: ${phVersion ?? 'auto'}) in ${options.targetDir} …`);
|
|
54
|
+
const run = options.runProcess;
|
|
55
|
+
if (run) {
|
|
56
|
+
const result = await run(`${binName} ${args.join(' ')}`, {
|
|
57
|
+
cwd: options.targetDir,
|
|
58
|
+
timeout: 300_000, // ph init + pnpm install can be slow
|
|
59
|
+
});
|
|
60
|
+
const exitCode = result.success ? 0 : 1;
|
|
61
|
+
if (!result.success) {
|
|
62
|
+
log(`\`${binName} init\` failed. ` +
|
|
63
|
+
'You can re-run it manually after resolving the issue.');
|
|
64
|
+
}
|
|
65
|
+
// Patch scoped name
|
|
66
|
+
await patchScopedName(options, appFolder, log);
|
|
67
|
+
return { ran: true, exitCode };
|
|
68
|
+
}
|
|
69
|
+
// Fallback: direct spawn with stdio inherit (for backward compat / tests without context)
|
|
70
|
+
const { runCommand } = await import('./exec.js');
|
|
71
|
+
const result = await runCommand(binName, args, { cwd: options.targetDir, stdio: 'inherit' });
|
|
31
72
|
if (result.exitCode !== 0) {
|
|
32
73
|
log(`\`${binName} init\` exited with code ${result.exitCode}. ` +
|
|
33
74
|
'You can re-run it manually after resolving the issue.');
|
|
34
75
|
}
|
|
76
|
+
await patchScopedName(options, appFolder, log);
|
|
35
77
|
return { ran: true, exitCode: result.exitCode };
|
|
36
78
|
}
|
|
79
|
+
async function patchScopedName(options, appFolder, log) {
|
|
80
|
+
if (!options.spec.scope)
|
|
81
|
+
return;
|
|
82
|
+
const appPkgJsonPath = path.join(options.appDir, 'package.json');
|
|
83
|
+
try {
|
|
84
|
+
const raw = await fs.readFile(appPkgJsonPath, 'utf8');
|
|
85
|
+
const pkg = JSON.parse(raw);
|
|
86
|
+
const scopedName = `@${options.spec.scope}/${appFolder}`;
|
|
87
|
+
if (pkg.name !== scopedName) {
|
|
88
|
+
pkg.name = scopedName;
|
|
89
|
+
pkg.publishConfig = { access: 'public' };
|
|
90
|
+
await fs.writeFile(appPkgJsonPath, JSON.stringify(pkg, null, 2) + '\n');
|
|
91
|
+
log(`Patched app package name to ${scopedName}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (err) {
|
|
95
|
+
log(`Warning: could not patch app package name: ${err instanceof Error ? err.message : String(err)}`);
|
|
96
|
+
}
|
|
97
|
+
}
|
|
37
98
|
export async function runPnpmInstall(options) {
|
|
38
99
|
const log = options.log ?? (() => { });
|
|
39
100
|
const binName = options.binName ?? 'pnpm';
|
|
@@ -45,14 +106,27 @@ export async function runPnpmInstall(options) {
|
|
|
45
106
|
const ran = [];
|
|
46
107
|
for (const dir of options.dirs) {
|
|
47
108
|
log(`Running \`${binName} install\` in ${dir} …`);
|
|
48
|
-
const
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
109
|
+
const run = options.runProcess;
|
|
110
|
+
if (run) {
|
|
111
|
+
const result = await run(`${binName} install`, {
|
|
112
|
+
cwd: dir,
|
|
113
|
+
timeout: 300_000,
|
|
114
|
+
});
|
|
115
|
+
if (!result.success) {
|
|
116
|
+
log(`\`${binName} install\` failed in ${dir}. ` +
|
|
117
|
+
'Retry manually once the underlying issue is resolved.');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
const { runCommand } = await import('./exec.js');
|
|
122
|
+
const result = await runCommand(binName, ['install'], {
|
|
123
|
+
cwd: dir,
|
|
124
|
+
stdio: 'inherit',
|
|
125
|
+
});
|
|
126
|
+
if (result.exitCode !== 0) {
|
|
127
|
+
log(`\`${binName} install\` exited with code ${result.exitCode} in ${dir}. ` +
|
|
128
|
+
'Retry manually once the underlying issue is resolved.');
|
|
129
|
+
}
|
|
56
130
|
}
|
|
57
131
|
ran.push(dir);
|
|
58
132
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import path from 'node:path';
|
|
2
|
-
import { spawn } from 'node:child_process';
|
|
3
2
|
import { defineCommand } from '@powerhousedao/ph-clint';
|
|
4
3
|
import { z } from 'zod';
|
|
5
4
|
import { detectLayout } from '@powerhousedao/ph-clint-dev';
|
|
@@ -7,44 +6,28 @@ const inputSchema = z.object({
|
|
|
7
6
|
dir: z.string().optional().describe('Project root directory (default: cwd)'),
|
|
8
7
|
verbose: z.boolean().default(false),
|
|
9
8
|
});
|
|
10
|
-
function execInDir(dir, cmd, verbose) {
|
|
11
|
-
return new Promise((resolve, reject) => {
|
|
12
|
-
const proc = spawn(cmd, {
|
|
13
|
-
cwd: dir,
|
|
14
|
-
shell: true,
|
|
15
|
-
stdio: verbose ? 'inherit' : 'pipe',
|
|
16
|
-
});
|
|
17
|
-
let stderr = '';
|
|
18
|
-
if (!verbose && proc.stderr) {
|
|
19
|
-
proc.stderr.on('data', (data) => {
|
|
20
|
-
stderr += data.toString();
|
|
21
|
-
});
|
|
22
|
-
}
|
|
23
|
-
proc.on('close', (code) => {
|
|
24
|
-
if (code === 0)
|
|
25
|
-
resolve();
|
|
26
|
-
else
|
|
27
|
-
reject(new Error(`Command "${cmd}" failed in ${dir} (exit ${code})${stderr ? `:\n${stderr}` : ''}`));
|
|
28
|
-
});
|
|
29
|
-
proc.on('error', (err) => reject(err));
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
9
|
export const build = defineCommand({
|
|
33
10
|
id: 'clint-project-build',
|
|
34
11
|
description: 'Build all packages in the project',
|
|
35
12
|
inputSchema,
|
|
36
|
-
execute: async (input, { workdir, stdout }) => {
|
|
13
|
+
execute: async (input, { workdir, stdout, runProcess }) => {
|
|
37
14
|
const dir = path.resolve(input.dir ?? workdir);
|
|
38
15
|
const layout = detectLayout(dir);
|
|
39
16
|
if (layout?.type === 'split') {
|
|
40
17
|
stdout(`Building app package (${layout.app})...\n`);
|
|
41
|
-
await
|
|
18
|
+
const appResult = await runProcess('pnpm build', { cwd: layout.app, timeout: 120_000 });
|
|
19
|
+
if (!appResult.success)
|
|
20
|
+
return { text: `App build failed.` };
|
|
42
21
|
stdout(`Building cli package (${layout.cli})...\n`);
|
|
43
|
-
await
|
|
22
|
+
const cliResult = await runProcess('pnpm build', { cwd: layout.cli, timeout: 120_000 });
|
|
23
|
+
if (!cliResult.success)
|
|
24
|
+
return { text: `CLI build failed.` };
|
|
44
25
|
}
|
|
45
26
|
else {
|
|
46
27
|
stdout(`Building project...\n`);
|
|
47
|
-
await
|
|
28
|
+
const result = await runProcess('pnpm build', { cwd: layout?.cli ?? dir, timeout: 120_000 });
|
|
29
|
+
if (!result.success)
|
|
30
|
+
return { text: `Build failed.` };
|
|
48
31
|
}
|
|
49
32
|
return { text: 'Build complete.' };
|
|
50
33
|
},
|
|
@@ -35,21 +35,45 @@ export declare const init: import("@powerhousedao/ph-clint").Command<z.ZodObject
|
|
|
35
35
|
version: string;
|
|
36
36
|
description: string;
|
|
37
37
|
features: {
|
|
38
|
-
powerhouse:
|
|
39
|
-
enabled: boolean;
|
|
40
|
-
switchboard: boolean;
|
|
41
|
-
connect: boolean;
|
|
42
|
-
};
|
|
38
|
+
powerhouse: "Disabled" | "Reactor" | "Switchboard" | "Connect";
|
|
43
39
|
mastra: {
|
|
44
40
|
enabled: boolean;
|
|
41
|
+
agentId: string | null;
|
|
42
|
+
agentName: string | null;
|
|
43
|
+
agentDescription: string | null;
|
|
44
|
+
agentImage: string | null;
|
|
45
|
+
models: {
|
|
46
|
+
id: string;
|
|
47
|
+
isDefault: boolean;
|
|
48
|
+
}[];
|
|
49
|
+
profiles: {
|
|
50
|
+
id: string;
|
|
51
|
+
title: string;
|
|
52
|
+
content: string;
|
|
53
|
+
}[];
|
|
45
54
|
};
|
|
46
55
|
routine: {
|
|
47
56
|
enabled: boolean;
|
|
48
57
|
};
|
|
49
58
|
};
|
|
50
|
-
|
|
59
|
+
packages: {
|
|
60
|
+
id: string;
|
|
61
|
+
packageName: string;
|
|
62
|
+
documentTypes: string[];
|
|
63
|
+
}[];
|
|
64
|
+
externalSkills: {
|
|
65
|
+
id: string;
|
|
66
|
+
name: string;
|
|
67
|
+
githubUrl: string;
|
|
68
|
+
}[];
|
|
69
|
+
deployment: {
|
|
70
|
+
serviceAnnouncement: boolean;
|
|
71
|
+
supportedResources: string[];
|
|
72
|
+
};
|
|
51
73
|
scope?: string | undefined;
|
|
52
74
|
bin?: string | undefined;
|
|
75
|
+
documentId?: string | undefined;
|
|
76
|
+
documentType?: string | undefined;
|
|
53
77
|
};
|
|
54
78
|
fileCount: number;
|
|
55
79
|
};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ph-clint init` — the project bootstrap wizard.
|
|
2
|
+
* `ph-clint clint-project-init` — the project bootstrap wizard.
|
|
3
3
|
*
|
|
4
4
|
* Behavior:
|
|
5
|
-
* 1. Resolve target dir (positional `dir`, defaults to
|
|
5
|
+
* 1. Resolve target dir (positional `dir`, defaults to the project name).
|
|
6
6
|
* 2. Assert it is empty (or `--force`).
|
|
7
7
|
* 3. Collect project identity + feature toggles (prompt for missing).
|
|
8
8
|
* 4. Assemble a ClintProjectSpec and validate with Zod.
|
|
@@ -13,16 +13,19 @@
|
|
|
13
13
|
*/
|
|
14
14
|
import path from 'node:path';
|
|
15
15
|
import { defineCommand } from '@powerhousedao/ph-clint';
|
|
16
|
+
import { importSpec } from '@powerhousedao/ph-clint-app/document-models/ph-clint-project';
|
|
16
17
|
import { z } from 'zod';
|
|
17
18
|
import { clintProjectSpecSchema, } from '../spec/types.js';
|
|
18
19
|
import { generateProject } from '../codegen/index.js';
|
|
19
20
|
import { isDirEmptyEnough } from '../codegen/write.js';
|
|
20
21
|
import { runPhInit, runPnpmInstall } from '../codegen/scaffold.js';
|
|
22
|
+
import { writeProjectSpec } from '../spec/file.js';
|
|
23
|
+
import { specToImportInput } from '../triggers/spec-change.js';
|
|
21
24
|
const inputSchema = z.object({
|
|
22
25
|
dir: z
|
|
23
26
|
.string()
|
|
24
27
|
.optional()
|
|
25
|
-
.describe('Target directory (defaults to the
|
|
28
|
+
.describe('Target directory (defaults to the project name)'),
|
|
26
29
|
name: z
|
|
27
30
|
.string()
|
|
28
31
|
.describe('Project name — bare, or `@scope/name`. Lowercase letters, digits, hyphens.'),
|
|
@@ -70,13 +73,22 @@ export function buildSpec(input) {
|
|
|
70
73
|
// Routine is forced on when Mastra is on — the REPL-only path works, but
|
|
71
74
|
// the agent routine loop is what most users actually want.
|
|
72
75
|
const routine = input.enableRoutine || input.enableMastra;
|
|
76
|
+
const mastra = input.enableMastra
|
|
77
|
+
? {
|
|
78
|
+
enabled: true,
|
|
79
|
+
agentId: `${name}-agent`,
|
|
80
|
+
agentName: `${name.charAt(0).toUpperCase()}${name.slice(1).replace(/-(\w)/g, (_, c) => ' ' + c.toUpperCase())} Agent`,
|
|
81
|
+
models: [{ id: 'anthropic/claude-sonnet-4-5', isDefault: true }],
|
|
82
|
+
profiles: [{ id: 'base', title: 'Base', content: 'You are a helpful assistant.' }],
|
|
83
|
+
}
|
|
84
|
+
: { enabled: false };
|
|
73
85
|
const candidate = {
|
|
74
86
|
name,
|
|
75
87
|
scope,
|
|
76
88
|
description: input.description ?? '',
|
|
77
89
|
features: {
|
|
78
|
-
powerhouse:
|
|
79
|
-
mastra
|
|
90
|
+
powerhouse: input.enablePowerhouse ? 'Connect' : 'Disabled',
|
|
91
|
+
mastra,
|
|
80
92
|
routine: { enabled: routine },
|
|
81
93
|
},
|
|
82
94
|
};
|
|
@@ -90,8 +102,9 @@ export const init = defineCommand({
|
|
|
90
102
|
promptForDefaults: true,
|
|
91
103
|
promptOptional: ['description'],
|
|
92
104
|
},
|
|
93
|
-
execute: async (input, { workdir, stdout }) => {
|
|
94
|
-
const
|
|
105
|
+
execute: async (input, { workdir, stdout, reactor: getReactor, folders, runProcess }) => {
|
|
106
|
+
const { name: bareName } = splitPackageName(input.name);
|
|
107
|
+
const targetDir = path.resolve(workdir, input.dir ?? bareName);
|
|
95
108
|
if (!input.force) {
|
|
96
109
|
const empty = await isDirEmptyEnough(targetDir);
|
|
97
110
|
if (!empty) {
|
|
@@ -109,7 +122,28 @@ export const init = defineCommand({
|
|
|
109
122
|
allowNonEmpty: input.force,
|
|
110
123
|
});
|
|
111
124
|
stdout(`Generated ${result.files.length} files in ${targetDir}\n`);
|
|
112
|
-
|
|
125
|
+
// Create spec document in personal drive (if reactor available)
|
|
126
|
+
if (getReactor && folders) {
|
|
127
|
+
try {
|
|
128
|
+
const reactor = await getReactor();
|
|
129
|
+
if (reactor) {
|
|
130
|
+
const newDoc = await reactor.client.createEmpty('powerhouse/ph-clint-project');
|
|
131
|
+
const docId = newDoc.header.id;
|
|
132
|
+
await folders.addDocument(docId, `specs/${spec.name}`, spec.name);
|
|
133
|
+
const importInput = specToImportInput(spec);
|
|
134
|
+
await reactor.client.execute(docId, 'main', [importSpec(importInput)]);
|
|
135
|
+
spec.documentId = docId;
|
|
136
|
+
spec.documentType = 'powerhouse/ph-clint-project';
|
|
137
|
+
await writeProjectSpec(targetDir, spec);
|
|
138
|
+
stdout(`Created spec document ${docId} in Clint Folders/specs/${spec.name}\n`);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
catch (err) {
|
|
142
|
+
// Non-fatal — trigger will pick it up on next startup
|
|
143
|
+
stdout(`Note: could not create spec document — ${err instanceof Error ? err.message : String(err)}\n`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
const split = spec.features.powerhouse !== 'Disabled';
|
|
113
147
|
// Reactor package scaffolding (split layout only).
|
|
114
148
|
if (split && result.appDir && !input.skipPhInit) {
|
|
115
149
|
const phResult = await runPhInit({
|
|
@@ -117,6 +151,7 @@ export const init = defineCommand({
|
|
|
117
151
|
appDir: result.appDir,
|
|
118
152
|
spec,
|
|
119
153
|
log: (msg) => stdout(msg + '\n'),
|
|
154
|
+
runProcess,
|
|
120
155
|
});
|
|
121
156
|
if (!phResult.ran) {
|
|
122
157
|
stdout(`Note: \`ph init\` did not run — ${phResult.reason ?? 'see above'}.\n`);
|
|
@@ -136,6 +171,7 @@ export const init = defineCommand({
|
|
|
136
171
|
await runPnpmInstall({
|
|
137
172
|
dirs,
|
|
138
173
|
log: (msg) => stdout(msg + '\n'),
|
|
174
|
+
runProcess,
|
|
139
175
|
});
|
|
140
176
|
}
|
|
141
177
|
const next = [];
|
|
@@ -159,7 +195,7 @@ export const init = defineCommand({
|
|
|
159
195
|
next.push(' pnpm dev');
|
|
160
196
|
}
|
|
161
197
|
next.push('');
|
|
162
|
-
next.push('Edit the project spec and run `ph-clint regen` to regenerate.');
|
|
198
|
+
next.push('Edit the project spec and run `ph-clint clint-project-regen` to regenerate.');
|
|
163
199
|
return {
|
|
164
200
|
text: next.join('\n'),
|
|
165
201
|
data: { targetDir, spec, fileCount: result.files.length },
|
|
@@ -8,6 +8,7 @@ export declare const clintProjectPublish: import("@powerhousedao/ph-clint").Comm
|
|
|
8
8
|
dir: z.ZodOptional<z.ZodString>;
|
|
9
9
|
dryRun: z.ZodDefault<z.ZodBoolean>;
|
|
10
10
|
skipBuild: z.ZodDefault<z.ZodBoolean>;
|
|
11
|
+
skipGitCheck: z.ZodDefault<z.ZodBoolean>;
|
|
11
12
|
verbose: z.ZodDefault<z.ZodBoolean>;
|
|
12
13
|
}, z.core.$strip>, {
|
|
13
14
|
text: string;
|
|
@@ -7,6 +7,7 @@ const inputSchema = z.object({
|
|
|
7
7
|
dir: z.string().optional().describe('Project root directory'),
|
|
8
8
|
dryRun: z.boolean().default(false).describe('Preview without publishing'),
|
|
9
9
|
skipBuild: z.boolean().default(false),
|
|
10
|
+
skipGitCheck: z.boolean().default(false).describe('Skip git working tree check'),
|
|
10
11
|
verbose: z.boolean().default(false),
|
|
11
12
|
});
|
|
12
13
|
function formatPlanPreview(plan) {
|
|
@@ -34,11 +35,12 @@ export const clintProjectPublish = defineCommand({
|
|
|
34
35
|
logLines.push(msg);
|
|
35
36
|
stdout(msg + '\n');
|
|
36
37
|
};
|
|
37
|
-
// 1. Resolve plan
|
|
38
|
+
// 1. Resolve plan — discover config from the target dir, not process.cwd().
|
|
39
|
+
const configFile = path.join(dir, 'publish.config.ts');
|
|
38
40
|
const plan = await resolvePublishPlan({
|
|
39
41
|
tag: input.tag,
|
|
40
|
-
configPath:
|
|
41
|
-
skipGitCheck: input.dryRun,
|
|
42
|
+
configPath: configFile,
|
|
43
|
+
skipGitCheck: input.dryRun || input.skipGitCheck,
|
|
42
44
|
log,
|
|
43
45
|
});
|
|
44
46
|
// 2. Show preview
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `ph-clint regen` — reconcile an existing project against its persisted
|
|
2
|
+
* `ph-clint clint-project-regen` — reconcile an existing project against its persisted
|
|
3
3
|
* spec. Equivalent to running the generator in update mode.
|
|
4
4
|
*
|
|
5
5
|
* Run inside a project directory (or pass `--dir`). If the spec has flipped
|
|
@@ -31,7 +31,7 @@ export const regen = defineCommand({
|
|
|
31
31
|
if (!spec) {
|
|
32
32
|
return {
|
|
33
33
|
text: `Error: no spec found at ${targetDir}/.ph/ph-clint-cli/project-spec.json.\n` +
|
|
34
|
-
'Run `ph-clint init` first to scaffold a new project.',
|
|
34
|
+
'Run `ph-clint clint-project-init` first to scaffold a new project.',
|
|
35
35
|
};
|
|
36
36
|
}
|
|
37
37
|
const warnings = [];
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export declare const skillsSync: import("@powerhousedao/ph-clint").Command<z.ZodObject<{
|
|
3
|
+
dir: z.ZodOptional<z.ZodString>;
|
|
4
|
+
}, z.core.$strip>, {
|
|
5
|
+
text: string;
|
|
6
|
+
data?: undefined;
|
|
7
|
+
} | {
|
|
8
|
+
text: string;
|
|
9
|
+
data: import("../skills/sync.js").SyncResult;
|
|
10
|
+
}, Record<string, unknown>>;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `ph-clint clint-skills-sync` — reconcile external skills on disk to match
|
|
3
|
+
* the project spec. Clones missing skills from GitHub, removes skills no
|
|
4
|
+
* longer referenced, and updates `.skills-manifest.json`.
|
|
5
|
+
*/
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { defineCommand } from '@powerhousedao/ph-clint';
|
|
8
|
+
import { z } from 'zod';
|
|
9
|
+
import { readProjectSpec } from '../spec/file.js';
|
|
10
|
+
import { syncExternalSkills } from '../skills/sync.js';
|
|
11
|
+
const inputSchema = z.object({
|
|
12
|
+
dir: z
|
|
13
|
+
.string()
|
|
14
|
+
.optional()
|
|
15
|
+
.describe('Project directory (defaults to the current directory)'),
|
|
16
|
+
});
|
|
17
|
+
export const skillsSync = defineCommand({
|
|
18
|
+
id: 'clint-skills-sync',
|
|
19
|
+
description: 'Synchronise external skills from the project spec',
|
|
20
|
+
inputSchema,
|
|
21
|
+
execute: async (input, { workdir, stdout, log }) => {
|
|
22
|
+
const targetDir = path.resolve(workdir, input.dir ?? '.');
|
|
23
|
+
const spec = await readProjectSpec(targetDir);
|
|
24
|
+
if (!spec) {
|
|
25
|
+
return {
|
|
26
|
+
text: `Error: no spec found at ${targetDir}/.ph/ph-clint-cli/project-spec.json.\n` +
|
|
27
|
+
'Run `ph-clint clint-project-init` first to scaffold a new project.',
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
const result = await syncExternalSkills({
|
|
31
|
+
targetDir,
|
|
32
|
+
desired: spec.externalSkills,
|
|
33
|
+
log: (msg) => {
|
|
34
|
+
if (log)
|
|
35
|
+
log.info(msg);
|
|
36
|
+
else
|
|
37
|
+
stdout(msg + '\n');
|
|
38
|
+
},
|
|
39
|
+
});
|
|
40
|
+
const lines = [];
|
|
41
|
+
if (result.added.length > 0) {
|
|
42
|
+
lines.push(`Added: ${result.added.join(', ')}`);
|
|
43
|
+
}
|
|
44
|
+
if (result.removed.length > 0) {
|
|
45
|
+
lines.push(`Removed: ${result.removed.join(', ')}`);
|
|
46
|
+
}
|
|
47
|
+
if (result.added.length === 0 && result.removed.length === 0) {
|
|
48
|
+
lines.push('External skills are up to date.');
|
|
49
|
+
}
|
|
50
|
+
stdout(lines.join('\n') + '\n');
|
|
51
|
+
return {
|
|
52
|
+
text: lines.join('\n'),
|
|
53
|
+
data: result,
|
|
54
|
+
};
|
|
55
|
+
},
|
|
56
|
+
});
|
package/dist/config.d.ts
CHANGED
|
@@ -1,5 +1,3 @@
|
|
|
1
|
-
|
|
2
|
-
export declare const CLI_NAME
|
|
3
|
-
export declare const CLI_VERSION
|
|
4
|
-
/** Project root — resolved from this file's location. */
|
|
5
|
-
export declare const PROJECT_ROOT: string;
|
|
1
|
+
export declare const CLI_ROOT: string;
|
|
2
|
+
export declare const CLI_NAME: string;
|
|
3
|
+
export declare const CLI_VERSION: string;
|
package/dist/config.js
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
export const CLI_NAME = '
|
|
5
|
-
export const CLI_VERSION =
|
|
6
|
-
/** Project root — resolved from this file's location. */
|
|
7
|
-
export const PROJECT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..');
|
|
1
|
+
import { readPackageInfo } from '@powerhousedao/ph-clint';
|
|
2
|
+
const pkg = readPackageInfo(import.meta.url);
|
|
3
|
+
export const CLI_ROOT = pkg.root;
|
|
4
|
+
export const CLI_NAME = pkg.name.replace(/-cli$/, '');
|
|
5
|
+
export const CLI_VERSION = pkg.version;
|