@powerhousedao/ph-clint-cli 0.1.0-dev.47 → 0.1.0-dev.49
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/codegen/actions.js
CHANGED
|
@@ -9,12 +9,14 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import fs from 'node:fs/promises';
|
|
11
11
|
import path from 'node:path';
|
|
12
|
+
import { getAppPackageName } from '../spec/types.js';
|
|
12
13
|
// ---------------------------------------------------------------------------
|
|
13
14
|
// Fixed execution order — index defines precedence
|
|
14
15
|
// ---------------------------------------------------------------------------
|
|
15
16
|
const ACTION_ORDER = [
|
|
16
17
|
'ph-init',
|
|
17
18
|
'app-install',
|
|
19
|
+
'app-ph-install',
|
|
18
20
|
'app-build',
|
|
19
21
|
'cli-install',
|
|
20
22
|
'cli-build',
|
|
@@ -28,11 +30,12 @@ function actionIndex(kind) {
|
|
|
28
30
|
// ---------------------------------------------------------------------------
|
|
29
31
|
/** Returns true if `downstream` depends on `upstream` succeeding. */
|
|
30
32
|
function dependsOn(downstream, upstream) {
|
|
31
|
-
// ph-init → app-install → app-build → cli-install → cli-build
|
|
33
|
+
// ph-init → app-install → app-ph-install → app-build → cli-install → cli-build
|
|
32
34
|
// skills-sync is independent of the build chain
|
|
33
35
|
const chain = [
|
|
34
36
|
'ph-init',
|
|
35
37
|
'app-install',
|
|
38
|
+
'app-ph-install',
|
|
36
39
|
'app-build',
|
|
37
40
|
'cli-install',
|
|
38
41
|
'cli-build',
|
|
@@ -57,6 +60,29 @@ async function fileExists(filePath) {
|
|
|
57
60
|
return false;
|
|
58
61
|
}
|
|
59
62
|
}
|
|
63
|
+
/** External packages that have document types (not the app package). */
|
|
64
|
+
function getExternalPackages(spec) {
|
|
65
|
+
const appPkg = getAppPackageName(spec);
|
|
66
|
+
return spec.packages.filter((p) => p.packageName !== appPkg && p.documentTypes.length > 0);
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns package names from `extPkgs` that are not yet registered in
|
|
70
|
+
* the app's `powerhouse.config.json`.
|
|
71
|
+
*/
|
|
72
|
+
async function getMissingPhPackages(appDir, extPkgs) {
|
|
73
|
+
try {
|
|
74
|
+
const raw = await fs.readFile(path.join(appDir, 'powerhouse.config.json'), 'utf8');
|
|
75
|
+
const config = JSON.parse(raw);
|
|
76
|
+
const registered = new Set((config.packages ?? []).map((p) => p.packageName));
|
|
77
|
+
return extPkgs
|
|
78
|
+
.map((p) => p.packageName)
|
|
79
|
+
.filter((name) => !registered.has(name));
|
|
80
|
+
}
|
|
81
|
+
catch {
|
|
82
|
+
// No config file yet (pre-init) — all packages are missing
|
|
83
|
+
return extPkgs.map((p) => p.packageName);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
60
86
|
// ---------------------------------------------------------------------------
|
|
61
87
|
// collectPostGenActions
|
|
62
88
|
// ---------------------------------------------------------------------------
|
|
@@ -133,6 +159,16 @@ export async function collectPostGenActions(result, spec) {
|
|
|
133
159
|
}
|
|
134
160
|
}
|
|
135
161
|
}
|
|
162
|
+
// Check if external packages need registering in the app
|
|
163
|
+
const extPkgs = split && result.appDir ? getExternalPackages(spec) : [];
|
|
164
|
+
if (split && result.appDir && extPkgs.length > 0) {
|
|
165
|
+
const missing = await getMissingPhPackages(result.appDir, extPkgs);
|
|
166
|
+
if (missing.length > 0) {
|
|
167
|
+
if (!earliest || actionIndex(earliest) > actionIndex('app-ph-install')) {
|
|
168
|
+
earliest = 'app-ph-install';
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
136
172
|
// Build the action list from earliest onward
|
|
137
173
|
const actions = [];
|
|
138
174
|
if (earliest && split && result.appDir) {
|
|
@@ -148,6 +184,12 @@ export async function collectPostGenActions(result, spec) {
|
|
|
148
184
|
if (ei <= actionIndex('app-install')) {
|
|
149
185
|
actions.push({ kind: 'app-install', dir: result.appDir });
|
|
150
186
|
}
|
|
187
|
+
if (ei <= actionIndex('app-ph-install') && extPkgs.length > 0) {
|
|
188
|
+
const missing = await getMissingPhPackages(result.appDir, extPkgs);
|
|
189
|
+
if (missing.length > 0) {
|
|
190
|
+
actions.push({ kind: 'app-ph-install', appDir: result.appDir, packages: missing });
|
|
191
|
+
}
|
|
192
|
+
}
|
|
151
193
|
if (ei <= actionIndex('app-build')) {
|
|
152
194
|
// Add install if not already in the list and node_modules is missing
|
|
153
195
|
if (!actions.some(a => a.kind === 'app-install') &&
|
|
@@ -202,6 +244,8 @@ function actionLabel(action) {
|
|
|
202
244
|
return `Initialize reactor package (${path.basename(action.appDir)})`;
|
|
203
245
|
case 'app-install':
|
|
204
246
|
return `Install dependencies (${path.basename(action.dir)})`;
|
|
247
|
+
case 'app-ph-install':
|
|
248
|
+
return `Register external packages (${action.packages.join(', ')})`;
|
|
205
249
|
case 'app-build':
|
|
206
250
|
return `Build (${path.basename(action.dir)})`;
|
|
207
251
|
case 'cli-install':
|
|
@@ -224,7 +268,9 @@ export async function runPostGenActions(actions, ctx) {
|
|
|
224
268
|
const effective = actions.filter((a) => {
|
|
225
269
|
if (skip.has(a.kind))
|
|
226
270
|
return false;
|
|
227
|
-
// If app-install is skipped, also skip app-build
|
|
271
|
+
// If app-install is skipped, also skip app-ph-install and app-build
|
|
272
|
+
if (a.kind === 'app-ph-install' && skip.has('app-install'))
|
|
273
|
+
return false;
|
|
228
274
|
if (a.kind === 'app-build' && skip.has('app-install'))
|
|
229
275
|
return false;
|
|
230
276
|
// If cli-install is skipped, also skip cli-build
|
|
@@ -332,6 +378,15 @@ async function executeAction(action, ctx) {
|
|
|
332
378
|
}
|
|
333
379
|
return result.exitCode === 0;
|
|
334
380
|
}
|
|
381
|
+
case 'app-ph-install': {
|
|
382
|
+
const { runPhInstallPackages } = await import('./scaffold.js');
|
|
383
|
+
return runPhInstallPackages({
|
|
384
|
+
appDir: action.appDir,
|
|
385
|
+
packages: action.packages,
|
|
386
|
+
log: (msg) => ctx.log(` ${msg}`),
|
|
387
|
+
runProcess: ctx.runProcess,
|
|
388
|
+
});
|
|
389
|
+
}
|
|
335
390
|
case 'app-install':
|
|
336
391
|
case 'cli-install': {
|
|
337
392
|
if (ctx.runProcess) {
|
|
@@ -4,6 +4,11 @@
|
|
|
4
4
|
* specific regions on subsequent runs (delta mode — future phase).
|
|
5
5
|
*/
|
|
6
6
|
import { getAppPackageName, phAtLeast } from '../../spec/types.js';
|
|
7
|
+
/** External packages that have document types (not the app package). */
|
|
8
|
+
function getExternalPackages(spec) {
|
|
9
|
+
const appPkg = getAppPackageName(spec);
|
|
10
|
+
return spec.packages.filter((p) => p.packageName !== appPkg && p.documentTypes.length > 0);
|
|
11
|
+
}
|
|
7
12
|
export function buildCliTs(spec) {
|
|
8
13
|
const { mastra, routine, powerhouse } = spec.features;
|
|
9
14
|
const ph = powerhouse;
|
|
@@ -29,6 +34,11 @@ export function buildCliTs(spec) {
|
|
|
29
34
|
lines.push(`import { configSchema, secretsSchema } from './framework.js';`);
|
|
30
35
|
if (phAtLeast(ph, 'Reactor')) {
|
|
31
36
|
lines.push(`import { documentModels } from '${getAppPackageName(spec)}';`);
|
|
37
|
+
const extPkgs = getExternalPackages(spec);
|
|
38
|
+
for (let i = 0; i < extPkgs.length; i++) {
|
|
39
|
+
const alias = extPkgs.length === 1 ? 'extModels' : `extModels${i}`;
|
|
40
|
+
lines.push(`import { documentModels as ${alias} } from '${extPkgs[i].packageName}';`);
|
|
41
|
+
}
|
|
32
42
|
}
|
|
33
43
|
if (mastra.enabled) {
|
|
34
44
|
lines.push(`import { createAgent } from './agents/agent.js';`);
|
|
@@ -131,8 +141,16 @@ export function buildCliTs(spec) {
|
|
|
131
141
|
lines.push('cli.configureReactor({');
|
|
132
142
|
lines.push(' create: (ctx) =>');
|
|
133
143
|
lines.push(' buildDefaultReactor(ctx, {');
|
|
134
|
-
|
|
144
|
+
const extPkgs = getExternalPackages(spec);
|
|
145
|
+
if (extPkgs.length === 0) {
|
|
146
|
+
lines.push(' documentModels,');
|
|
147
|
+
}
|
|
148
|
+
else {
|
|
149
|
+
const aliases = extPkgs.map((_, i) => extPkgs.length === 1 ? 'extModels' : `extModels${i}`);
|
|
150
|
+
lines.push(` documentModels: [...documentModels, ${aliases.map(a => `...${a}`).join(', ')}],`);
|
|
151
|
+
}
|
|
135
152
|
lines.push(` drive: { name: '${spec.name}' },`);
|
|
153
|
+
lines.push(' subscriptions: {},');
|
|
136
154
|
lines.push(' }),');
|
|
137
155
|
lines.push(` switchboard: { enabled: ${String(phAtLeast(ph, 'Switchboard'))} },`);
|
|
138
156
|
lines.push(` connect: { enabled: ${String(phAtLeast(ph, 'Connect'))} },`);
|
|
@@ -44,6 +44,16 @@ export declare function patchAppPackageName(appDir: string, spec: {
|
|
|
44
44
|
name: string;
|
|
45
45
|
scope?: string;
|
|
46
46
|
}, log?: (msg: string) => void): Promise<boolean>;
|
|
47
|
+
/**
|
|
48
|
+
* Run `ph install <packages> --local --pnpm` in the app directory to register
|
|
49
|
+
* external packages in `powerhouse.config.json`.
|
|
50
|
+
*/
|
|
51
|
+
export declare function runPhInstallPackages(options: {
|
|
52
|
+
appDir: string;
|
|
53
|
+
packages: string[];
|
|
54
|
+
log?: (msg: string) => void;
|
|
55
|
+
runProcess?: RunProcess;
|
|
56
|
+
}): Promise<boolean>;
|
|
47
57
|
export interface PnpmInstallOptions {
|
|
48
58
|
/** Directories to run `pnpm install` in, in order. */
|
|
49
59
|
dirs: string[];
|
package/dist/codegen/scaffold.js
CHANGED
|
@@ -119,6 +119,33 @@ export async function patchAppPackageName(appDir, spec, log) {
|
|
|
119
119
|
async function patchScopedName(options, _appFolder, log) {
|
|
120
120
|
await patchAppPackageName(options.appDir, options.spec, log);
|
|
121
121
|
}
|
|
122
|
+
/**
|
|
123
|
+
* Run `ph install <packages> --local --pnpm` in the app directory to register
|
|
124
|
+
* external packages in `powerhouse.config.json`.
|
|
125
|
+
*/
|
|
126
|
+
export async function runPhInstallPackages(options) {
|
|
127
|
+
const { appDir, packages, log = () => { }, runProcess } = options;
|
|
128
|
+
const binName = 'ph';
|
|
129
|
+
if (!(await hasCommandOnPath(binName))) {
|
|
130
|
+
log(`Skipping — \`${binName}\` is not on PATH.`);
|
|
131
|
+
return false;
|
|
132
|
+
}
|
|
133
|
+
const args = ['install', ...packages, '--local', '--pnpm'];
|
|
134
|
+
log(`Running \`${binName} install ${packages.join(' ')} --local\` in ${path.basename(appDir)} …`);
|
|
135
|
+
if (runProcess) {
|
|
136
|
+
const result = await runProcess(`${binName} ${args.join(' ')}`, {
|
|
137
|
+
cwd: appDir,
|
|
138
|
+
timeout: 300_000,
|
|
139
|
+
});
|
|
140
|
+
return result.success;
|
|
141
|
+
}
|
|
142
|
+
const { runCommand } = await import('./exec.js');
|
|
143
|
+
const result = await runCommand(binName, args, {
|
|
144
|
+
cwd: appDir,
|
|
145
|
+
stdio: 'inherit',
|
|
146
|
+
});
|
|
147
|
+
return result.exitCode === 0;
|
|
148
|
+
}
|
|
122
149
|
export async function runPnpmInstall(options) {
|
|
123
150
|
const log = options.log ?? (() => { });
|
|
124
151
|
const binName = options.binName ?? 'pnpm';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@powerhousedao/ph-clint-cli",
|
|
3
|
-
"version": "0.1.0-dev.
|
|
3
|
+
"version": "0.1.0-dev.49",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -29,9 +29,9 @@
|
|
|
29
29
|
"@mastra/core": "^1.22.0",
|
|
30
30
|
"@mastra/libsql": "^1.7.4",
|
|
31
31
|
"@mastra/memory": "^1.13.1",
|
|
32
|
-
"@powerhousedao/ph-clint": "^0.1.0-dev.
|
|
33
|
-
"@powerhousedao/ph-clint-app": "^0.1.0-dev.
|
|
34
|
-
"@powerhousedao/ph-clint-dev": "^0.1.0-dev.
|
|
32
|
+
"@powerhousedao/ph-clint": "^0.1.0-dev.49",
|
|
33
|
+
"@powerhousedao/ph-clint-app": "^0.1.0-dev.49",
|
|
34
|
+
"@powerhousedao/ph-clint-dev": "^0.1.0-dev.49",
|
|
35
35
|
"@powerhousedao/reactor": "6.0.0-dev.170",
|
|
36
36
|
"@powerhousedao/reactor-api": "6.0.0-dev.170",
|
|
37
37
|
"@powerhousedao/shared": "6.0.0-dev.170",
|