@powerhousedao/ph-clint-cli 0.1.0-dev.7 → 0.1.0-dev.70

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.
Files changed (101) hide show
  1. package/dist/cli.js +52 -10
  2. package/dist/codegen/actions.d.ts +1 -0
  3. package/dist/codegen/actions.js +1 -0
  4. package/dist/codegen/builders/agent-ts.d.ts +4 -4
  5. package/dist/codegen/builders/agent-ts.js +92 -2
  6. package/dist/codegen/builders/app-index-ts.d.ts +3 -10
  7. package/dist/codegen/builders/app-index-ts.js +30 -20
  8. package/dist/codegen/builders/cli-package-json.d.ts +1 -8
  9. package/dist/codegen/builders/cli-package-json.js +1 -96
  10. package/dist/codegen/builders/cli-ts.js +88 -37
  11. package/dist/codegen/builders/config-ts.d.ts +1 -1
  12. package/dist/codegen/builders/config-ts.js +2 -8
  13. package/dist/codegen/builders/demo-agent-ts.d.ts +8 -0
  14. package/dist/codegen/builders/demo-agent-ts.js +50 -0
  15. package/dist/codegen/builders/eslint-config-js.d.ts +1 -1
  16. package/dist/codegen/builders/eslint-config-js.js +7 -4
  17. package/dist/codegen/builders/framework-gen-ts.d.ts +11 -6
  18. package/dist/codegen/builders/framework-gen-ts.js +73 -21
  19. package/dist/codegen/builders/framework-ts.js +33 -7
  20. package/dist/codegen/builders/index.d.ts +1 -44
  21. package/dist/codegen/builders/index.js +1 -61
  22. package/dist/codegen/builders/manifest-json.d.ts +6 -0
  23. package/dist/codegen/builders/manifest-json.js +31 -0
  24. package/dist/codegen/builders/mastra-index-ts.d.ts +3 -0
  25. package/dist/codegen/builders/mastra-index-ts.js +47 -5
  26. package/dist/codegen/builders/publish-config-js.d.ts +8 -0
  27. package/dist/codegen/builders/publish-config-js.js +33 -0
  28. package/dist/codegen/builders/publish-config-ts.d.ts +4 -2
  29. package/dist/codegen/builders/publish-config-ts.js +25 -11
  30. package/dist/codegen/builders/readme-md.js +7 -6
  31. package/dist/codegen/builders/root-package-json.js +14 -11
  32. package/dist/codegen/builders/smoke-test-ts.d.ts +2 -0
  33. package/dist/codegen/builders/smoke-test-ts.js +15 -0
  34. package/dist/codegen/exec.d.ts +1 -20
  35. package/dist/codegen/exec.js +1 -41
  36. package/dist/codegen/generated.d.ts +1 -0
  37. package/dist/codegen/generated.js +1 -0
  38. package/dist/codegen/hashes.d.ts +1 -6
  39. package/dist/codegen/hashes.js +1 -60
  40. package/dist/codegen/index.d.ts +8 -36
  41. package/dist/codegen/index.js +6 -293
  42. package/dist/codegen/markers.d.ts +1 -36
  43. package/dist/codegen/markers.js +1 -86
  44. package/dist/codegen/scaffold.d.ts +1 -34
  45. package/dist/codegen/scaffold.js +1 -60
  46. package/dist/codegen/write.d.ts +1 -6
  47. package/dist/codegen/write.js +1 -32
  48. package/dist/commands/clint-project-build.d.ts +6 -1
  49. package/dist/commands/clint-project-build.js +11 -28
  50. package/dist/commands/clint-project-init.d.ts +45 -10
  51. package/dist/commands/clint-project-init.js +61 -47
  52. package/dist/commands/clint-project-publish.d.ts +7 -1
  53. package/dist/commands/clint-project-publish.js +6 -4
  54. package/dist/commands/clint-project-regen.d.ts +6 -1
  55. package/dist/commands/clint-project-regen.js +26 -2
  56. package/dist/commands/clint-skills-sync.d.ts +15 -0
  57. package/dist/commands/clint-skills-sync.js +56 -0
  58. package/dist/framework.d.ts +6 -170
  59. package/dist/framework.gen.d.ts +1 -32
  60. package/dist/framework.js +1 -5
  61. package/{prompts/agent-profiles/AgentBase.md → dist/gen/agent-profiles/PhClintDevAgent.md} +1 -1
  62. package/dist/gen/skills/cli-setup/.cli-docs.md +135 -0
  63. package/dist/gen/skills/cli-setup/SKILL.md +125 -0
  64. package/dist/gen/skills/cli-setup/references/00.assess-cli-needs.md +53 -0
  65. package/dist/gen/skills/cli-setup/references/01.define-config-schema.md +78 -0
  66. package/dist/gen/skills/cli-setup/references/02.wire-cli.md +141 -0
  67. package/dist/gen/skills/cli-setup/references/03.add-entrypoint.md +128 -0
  68. package/dist/gen/skills/cli-setup/references/expected-outcome.md +3 -0
  69. package/dist/gen/skills/command-definition/.cli-docs.md +84 -0
  70. package/dist/gen/skills/command-definition/SKILL.md +99 -0
  71. package/dist/gen/skills/command-definition/references/00.assess-requirements.md +58 -0
  72. package/dist/gen/skills/command-definition/references/01.define-schema.md +72 -0
  73. package/dist/gen/skills/command-definition/references/02.implement-execute.md +118 -0
  74. package/dist/gen/skills/command-definition/references/03.add-prompting.md +54 -0
  75. package/dist/gen/skills/command-definition/references/expected-outcome.md +3 -0
  76. package/dist/gen/skills/service-definition/.cli-docs.md +214 -0
  77. package/dist/gen/skills/service-definition/SKILL.md +148 -0
  78. package/dist/gen/skills/service-definition/references/00.assess-service.md +69 -0
  79. package/dist/gen/skills/service-definition/references/01.define-service.md +166 -0
  80. package/dist/gen/skills/service-definition/references/02.add-preflight.md +132 -0
  81. package/dist/gen/skills/service-definition/references/03.add-project-scanner.md +82 -0
  82. package/dist/gen/skills/service-definition/references/04.wire-events.md +120 -0
  83. package/dist/gen/skills/service-definition/references/expected-outcome.md +3 -0
  84. package/dist/services/clint-project.js +21 -0
  85. package/dist/skills/sync.d.ts +1 -0
  86. package/dist/skills/sync.js +1 -0
  87. package/dist/spec/ensure-document.d.ts +17 -0
  88. package/dist/spec/ensure-document.js +56 -0
  89. package/dist/spec/file.d.ts +1 -4
  90. package/dist/spec/file.js +1 -34
  91. package/dist/spec/from-document.d.ts +4 -1
  92. package/dist/spec/from-document.js +4 -16
  93. package/dist/spec/types.d.ts +1 -62
  94. package/dist/spec/types.js +1 -112
  95. package/dist/triggers/publish-trigger.d.ts +10 -0
  96. package/dist/triggers/publish-trigger.js +137 -0
  97. package/dist/triggers/spec-change.d.ts +5 -34
  98. package/dist/triggers/spec-change.js +137 -102
  99. package/package.json +12 -17
  100. package/prompts/skills-ext/.gitkeep +0 -0
  101. package/prompts/skills-tpl/.gitkeep +0 -0
package/dist/cli.js CHANGED
@@ -7,7 +7,8 @@
7
7
  * Everything outside the markers is user-editable and preserved.
8
8
  */
9
9
  import path from 'node:path';
10
- import { defineCli, buildDefaultReactor } from '@powerhousedao/ph-clint';
10
+ import { defineCli, buildDefaultReactor, deterministicId } from '@powerhousedao/ph-clint';
11
+ import { z } from 'zod';
11
12
  import { CLI_NAME, CLI_VERSION, CLI_ROOT } from './config.js';
12
13
  import { configSchema, secretsSchema } from './framework.js';
13
14
  // @clint:begin imports
@@ -18,30 +19,69 @@ import { regen } from './commands/clint-project-regen.js';
18
19
  import { build } from './commands/clint-project-build.js';
19
20
  import { clintProjectPublish } from './commands/clint-project-publish.js';
20
21
  import { clintProject } from './services/clint-project.js';
22
+ import { skillsSync } from './commands/clint-skills-sync.js';
21
23
  import { specChangeTrigger } from './triggers/spec-change.js';
24
+ import { publishTrigger } from './triggers/publish-trigger.js';
22
25
  // @clint:end imports
23
- // Connect (ph connect) must run inside the Reactor Package (ph-clint-app).
24
- const appDir = path.resolve(CLI_ROOT, '../ph-clint-app');
25
26
  export const cli = defineCli({
26
27
  name: CLI_NAME,
27
28
  version: CLI_VERSION,
29
+ root: CLI_ROOT,
28
30
  description: `${CLI_NAME} v${CLI_VERSION} — scaffold and maintain ph-clint implementation projects`,
29
31
  configSchema,
30
32
  secretsSchema,
31
33
  // @clint:begin commands
32
- commands: [init, regen, build, clintProjectPublish],
34
+ commands: [init, regen, build, clintProjectPublish, skillsSync],
33
35
  // @clint:end commands
34
36
  // @clint:begin services
35
37
  services: [clintProject],
36
38
  // @clint:end services
37
39
  // @clint:begin triggers
38
- triggers: [specChangeTrigger],
40
+ triggers: [specChangeTrigger, publishTrigger],
41
+ routine: { id: 'triggers', name: 'Triggers' },
39
42
  // @clint:end triggers
40
43
  // @clint:begin prompts
41
44
  prompts: {
42
- sources: [],
43
- agents: {},
44
- skills: {},
45
+ artifacts: [path.join(CLI_ROOT, 'gen', 'skills'), path.join(CLI_ROOT, 'dist', 'gen', 'skills')],
46
+ agents: {
47
+ 'ph-clint-dev-agent': {
48
+ name: 'PhClintDevAgent',
49
+ sections: ['AgentBase.md'],
50
+ skills: ['cli-setup', 'command-definition', 'service-definition'],
51
+ },
52
+ },
53
+ skills: {
54
+ 'cli-setup': {
55
+ description: 'Set up a new CLI with defineCli, config schemas, entrypoint, and interactive mode',
56
+ inputSchema: z.object({
57
+ mode: z
58
+ .enum(['expert', 'discovery', 'one-shot'])
59
+ .default('expert')
60
+ .describe('Expert: align design decisions with the developer. Discovery: explain concepts step by step. One-shot: make all decisions autonomously'),
61
+ }),
62
+ instructionTemplate: 'Use your {{skillId}} skill in {{mode}} mode for: {{prompt}}',
63
+ },
64
+ 'command-definition': {
65
+ description: 'Define commands with Zod schemas, execute functions, return values, and parameter prompting',
66
+ inputSchema: z.object({
67
+ mode: z
68
+ .enum(['expert', 'discovery', 'one-shot'])
69
+ .default('expert')
70
+ .describe('Expert: align design decisions with the developer. Discovery: explain concepts step by step. One-shot: make all decisions autonomously'),
71
+ }),
72
+ instructionTemplate: 'Use your {{skillId}} skill in {{mode}} mode for: {{prompt}}',
73
+ },
74
+ 'service-definition': {
75
+ description: 'Define background services with readiness detection, preflight checks, and project scanning',
76
+ inputSchema: z.object({
77
+ mode: z
78
+ .enum(['expert', 'discovery', 'one-shot'])
79
+ .default('expert')
80
+ .describe('Expert: align design decisions with the developer. Discovery: explain concepts step by step. One-shot: make all decisions autonomously'),
81
+ }),
82
+ instructionTemplate: 'Use your {{skillId}} skill in {{mode}} mode for: {{prompt}}',
83
+ },
84
+ },
45
85
  },
46
86
  // @clint:end prompts
47
87
  // @clint:begin events
@@ -68,11 +108,13 @@ export const cli = defineCli({
68
108
  cli.configureReactor({
69
109
  create: (ctx) => buildDefaultReactor(ctx, {
70
110
  documentModels,
71
- drive: { name: 'Clint' },
111
+ drives: [
112
+ { name: 'Clint Folders', role: 'personal', id: deterministicId(CLI_NAME, 'personal-drive') },
113
+ ],
72
114
  subscriptions: { documentTypes: ['powerhouse/ph-clint-project'] },
73
115
  }),
74
116
  switchboard: { enabled: true },
75
- connect: { enabled: true, workdir: appDir },
117
+ connect: { enabled: true },
76
118
  });
77
119
  // @clint:end reactor
78
120
  // @clint:begin mastra
@@ -0,0 +1 @@
1
+ export { type PostGenAction, type PostGenActionKind, type PostGenActionContext, type PostGenActionResult, collectPostGenActions, runPostGenActions, } from '@powerhousedao/ph-clint-dev/codegen/actions';
@@ -0,0 +1 @@
1
+ export { collectPostGenActions, runPostGenActions, } from '@powerhousedao/ph-clint-dev/codegen/actions';
@@ -1,9 +1,9 @@
1
1
  /**
2
- * Builds `src/agents/agent.ts` — a minimal Mastra agent factory.
2
+ * Builds `src/agents/agent.ts` — a Mastra agent factory.
3
3
  *
4
- * Emitted only when `features.mastra.enabled`. The generated agent falls back
5
- * to a deterministic echo-style demo provider when no API key is configured,
6
- * so `pnpm dev` works immediately out of the box.
4
+ * Emitted only when `features.mastra.enabled`. When the spec includes agent
5
+ * config (agentId, models, profiles), generates a real `@mastra/core` Agent.
6
+ * Otherwise falls back to a deterministic echo-style demo provider.
7
7
  */
8
8
  import { type ClintProjectSpec } from '../../spec/types.js';
9
9
  export declare function buildAgentTs(spec: ClintProjectSpec): string;
@@ -1,5 +1,20 @@
1
- export function buildAgentTs(spec) {
2
- const id = spec.name;
1
+ /** Map provider prefix to AI SDK package. */
2
+ function providerImport(provider) {
3
+ switch (provider) {
4
+ case 'anthropic':
5
+ return { pkg: '@ai-sdk/anthropic', fn: 'anthropic' };
6
+ case 'openai':
7
+ return { pkg: '@ai-sdk/openai', fn: 'openai' };
8
+ case 'google':
9
+ return { pkg: '@ai-sdk/google', fn: 'google' };
10
+ default:
11
+ return { pkg: `@ai-sdk/${provider}`, fn: provider };
12
+ }
13
+ }
14
+ function buildDemoAgent(spec) {
15
+ const mastra = spec.features.mastra;
16
+ const id = mastra.agentId ?? spec.name;
17
+ const name = mastra.agentName ?? id;
3
18
  return [
4
19
  "import type { AgentProvider, AgentSetupContext, StreamChunk } from '@powerhousedao/ph-clint';",
5
20
  "import type { Config } from '../framework.js';",
@@ -11,6 +26,7 @@ export function buildAgentTs(spec) {
11
26
  'function createDemoAgent(): AgentProvider {',
12
27
  ' return {',
13
28
  ` id: '${id}',`,
29
+ ` name: '${name}',`,
14
30
  ' async *stream(prompt) {',
15
31
  ' yield {',
16
32
  " type: 'text-delta',",
@@ -32,3 +48,77 @@ export function buildAgentTs(spec) {
32
48
  '',
33
49
  ].join('\n');
34
50
  }
51
+ function buildRealAgent(spec) {
52
+ const mastra = spec.features.mastra;
53
+ const agentId = mastra.agentId;
54
+ const agentName = mastra.agentName;
55
+ const defaultModel = mastra.models.find(m => m.isDefault) ?? mastra.models[0];
56
+ const modelId = defaultModel?.id ?? 'anthropic/claude-sonnet-4-5';
57
+ const [provider] = modelId.split(/[:/]/);
58
+ const { pkg, fn } = providerImport(provider);
59
+ const apiKeyField = `${provider}ApiKey`;
60
+ const lines = [];
61
+ lines.push("import { Agent } from '@mastra/core/agent';");
62
+ lines.push("import { MCPClient } from '@mastra/mcp';");
63
+ lines.push("import { createMastraHelpers } from '@powerhousedao/ph-clint/mastra';");
64
+ lines.push("import { createWorkdirStore } from '@powerhousedao/ph-clint';");
65
+ lines.push("import type { AgentSetupContext, AgentProvider } from '@powerhousedao/ph-clint';");
66
+ lines.push("import type { WrapAgentOptions } from '@powerhousedao/ph-clint/mastra';");
67
+ lines.push("import { CLI_NAME } from '../config.js';");
68
+ lines.push("import type { Config } from '../framework.js';");
69
+ lines.push("import { createDemoAgent } from './demo-agent.js';");
70
+ lines.push('');
71
+ lines.push('/**');
72
+ lines.push(' * Agent factory for the CLI.');
73
+ lines.push(' *');
74
+ lines.push(' * Returns a demo agent when no API key is configured, or wraps the full');
75
+ lines.push(' * agent as a ph-clint AgentProvider.');
76
+ lines.push(' */');
77
+ lines.push('export async function createAgent(ctx: AgentSetupContext<Config>): Promise<AgentProvider> {');
78
+ lines.push(` if (!ctx.config.${apiKeyField}) return createDemoAgent();`);
79
+ lines.push('');
80
+ lines.push(' const m = createMastraHelpers(ctx);');
81
+ lines.push('');
82
+ lines.push(' const agent = new Agent({');
83
+ lines.push(` id: '${agentId}',`);
84
+ lines.push(` name: '${agentName}',`);
85
+ lines.push(` instructions: m.getAgentInstructions('${agentId}'),`);
86
+ lines.push(` model: ctx.config.${apiKeyField}`);
87
+ lines.push(` ? { id: ctx.config.model as \`\${string}/\${string}\`, apiKey: ctx.config.${apiKeyField} }`);
88
+ lines.push(` : (ctx.config.model as \`\${string}/\${string}\`),`);
89
+ lines.push(' tools: async () => {');
90
+ lines.push(" ctx.context.log?.debug('[agent] tools callback invoked');");
91
+ lines.push(' const tools = await m.getTools({ MCPClient });');
92
+ lines.push(" ctx.context.log?.debug(`[agent] tools resolved: ${Object.keys(tools).length} tools`);");
93
+ lines.push(' return tools;');
94
+ lines.push(' },');
95
+ lines.push(' workspace: await m.createWorkspace(),');
96
+ lines.push(' memory: await m.createMemory(),');
97
+ lines.push(' });');
98
+ lines.push('');
99
+ lines.push(' const store = createWorkdirStore(ctx.workdir, CLI_NAME);');
100
+ lines.push(' const wrapOpts: WrapAgentOptions = {');
101
+ lines.push(' maxSteps: 80,');
102
+ lines.push(' enableLogging: ctx.config.agentLogging,');
103
+ lines.push(" logDirectory: store.getStoreFolder('logs'),");
104
+ lines.push(' cacheControl: true,');
105
+ if (mastra.agentDescription) {
106
+ lines.push(` description: ${JSON.stringify(mastra.agentDescription)},`);
107
+ }
108
+ if (mastra.agentImage) {
109
+ lines.push(` image: ${JSON.stringify(mastra.agentImage)},`);
110
+ }
111
+ lines.push(' };');
112
+ lines.push(' return m.wrapAgent(agent, wrapOpts);');
113
+ lines.push('}');
114
+ lines.push('');
115
+ return lines.join('\n');
116
+ }
117
+ export function buildAgentTs(spec) {
118
+ const mastra = spec.features.mastra;
119
+ // Generate real agent when we have full config, demo otherwise
120
+ if (mastra.agentId && mastra.models.length > 0) {
121
+ return buildRealAgent(spec);
122
+ }
123
+ return buildDemoAgent(spec);
124
+ }
@@ -3,16 +3,9 @@
3
3
  * reactor package. Impl code imports from `'{name}-app'` instead of drilling
4
4
  * into `'{name}-app/document-models/<slug>/v1/gen/...'`.
5
5
  *
6
- * Each entry re-exports a document-model subfolder's `index.ts`, which in
7
- * turn re-exports the module object (`PhClintProject`, ...), action creators,
8
- * document/state types, and type guards. Fully machine-owned: regen on every
9
- * run.
10
- *
11
- * Powerhouse's own codegen might emit its own `index.ts` (as is the case for
12
- * ph-clint-app today, which has manifest/editors/processors re-exports). When
13
- * that exists, leave it alone — users hand-merge. Our codegen only emits when
14
- * the file is absent or was emitted by a previous ph-clint-cli run (hash
15
- * matches the ledger).
6
+ * Only re-exports document types belonging to the app package (the project's
7
+ * own reactor package). External packages' document types are imported from
8
+ * their own npm packages, not from the app barrel.
16
9
  */
17
10
  import { type ClintProjectSpec } from '../../spec/types.js';
18
11
  export declare function buildAppIndexTs(spec: ClintProjectSpec): string | null;
@@ -3,31 +3,41 @@
3
3
  * reactor package. Impl code imports from `'{name}-app'` instead of drilling
4
4
  * into `'{name}-app/document-models/<slug>/v1/gen/...'`.
5
5
  *
6
- * Each entry re-exports a document-model subfolder's `index.ts`, which in
7
- * turn re-exports the module object (`PhClintProject`, ...), action creators,
8
- * document/state types, and type guards. Fully machine-owned: regen on every
9
- * run.
10
- *
11
- * Powerhouse's own codegen might emit its own `index.ts` (as is the case for
12
- * ph-clint-app today, which has manifest/editors/processors re-exports). When
13
- * that exists, leave it alone — users hand-merge. Our codegen only emits when
14
- * the file is absent or was emitted by a previous ph-clint-cli run (hash
15
- * matches the ledger).
6
+ * Only re-exports document types belonging to the app package (the project's
7
+ * own reactor package). External packages' document types are imported from
8
+ * their own npm packages, not from the app barrel.
16
9
  */
17
- import { getDocumentTypeSlug, } from '../../spec/types.js';
10
+ import { getAppPackageName, getDocumentTypeSlug, isDocTypeGlob, phAtLeast, } from '../../spec/types.js';
18
11
  export function buildAppIndexTs(spec) {
19
- if (!spec.features.powerhouse.enabled)
20
- return null;
21
- if (spec.documentTypes.length === 0)
12
+ if (!phAtLeast(spec.features.powerhouse, 'Reactor'))
22
13
  return null;
23
14
  const lines = [];
15
+ // Standard Powerhouse reactor-package barrel — matches what `ph init`
16
+ // generates. Required by main.tsx (Connect) and cli.ts imports.
24
17
  lines.push('// THIS FILE IS GENERATED BY ph-clint-cli.');
25
- lines.push('// Re-exports every registered document model from a single top-level');
26
- lines.push('// entry so impl code can `import { ... } from \'{name}-app\'`.');
27
- lines.push('');
28
- for (const docType of spec.documentTypes) {
29
- const slug = getDocumentTypeSlug(docType);
30
- lines.push(`export * from './document-models/${slug}/index.js';`);
18
+ lines.push("import type { Manifest } from 'document-model';");
19
+ lines.push("import manifestJson from './powerhouse.manifest.json' with { type: 'json' };");
20
+ lines.push("export { documentModels } from './document-models/document-models.js';");
21
+ lines.push("export { upgradeManifests } from './document-models/upgrade-manifests.js';");
22
+ lines.push("export { editors } from './editors/editors.js';");
23
+ lines.push("export { processorFactory } from './processors/factory.js';");
24
+ lines.push('export const manifest: Manifest = manifestJson;');
25
+ // Per-document-type re-exports so impl code can import from
26
+ // '{name}-app' instead of drilling into deep paths.
27
+ const appPkg = getAppPackageName(spec);
28
+ const appEntry = spec.packages.find((p) => p.packageName === appPkg);
29
+ const docTypes = appEntry?.documentTypes ?? [];
30
+ if (docTypes.length > 0) {
31
+ const hasGlobs = docTypes.some(isDocTypeGlob);
32
+ const explicits = docTypes.filter((dt) => !isDocTypeGlob(dt));
33
+ lines.push('');
34
+ if (hasGlobs) {
35
+ lines.push("export * from './document-models/index.js';");
36
+ }
37
+ for (const docType of explicits) {
38
+ const slug = getDocumentTypeSlug(docType);
39
+ lines.push(`export * from './document-models/${slug}/index.js';`);
40
+ }
31
41
  }
32
42
  return lines.join('\n') + '\n';
33
43
  }
@@ -1,8 +1 @@
1
- /**
2
- * Builds the CLI-side `package.json` (the ph-clint CLI itself).
3
- *
4
- * When `features.powerhouse.enabled`, this file lives at
5
- * `{root}/{name}-cli/package.json`. Otherwise at `{root}/package.json`.
6
- */
7
- import { type ClintProjectSpec } from '../../spec/types.js';
8
- export declare function buildCliPackageJson(spec: ClintProjectSpec): string;
1
+ export { buildCliPackageJson } from '@powerhousedao/ph-clint-dev/codegen/builders';
@@ -1,96 +1 @@
1
- /**
2
- * Builds the CLI-side `package.json` (the ph-clint CLI itself).
3
- *
4
- * When `features.powerhouse.enabled`, this file lives at
5
- * `{root}/{name}-cli/package.json`. Otherwise at `{root}/package.json`.
6
- */
7
- import { getBinName, getPackageName, } from '../../spec/types.js';
8
- import { CLI_VERSION } from '../../config.js';
9
- /**
10
- * Derive a semver range from the running ph-clint-cli version that respects
11
- * the dev / staging / production channel boundary. This is the version range
12
- * emitted into *scaffolded* projects' package.json for @powerhousedao/ph-clint
13
- * and @powerhousedao/ph-clint-dev dependencies.
14
- *
15
- * CLI_VERSION is the version of ph-clint-cli itself (read from its own
16
- * package.json at startup). Since all framework packages share a lockstep
17
- * version, this is also the correct base for the dependency range.
18
- *
19
- * Examples:
20
- * "0.1.0" → "^0.1.0" (production — stable only)
21
- * "0.1.0-staging.2" → "^0.1.0-staging.0" (staging + stable)
22
- * "0.1.0-dev.4" → "^0.1.0-dev.0" (dev + staging + stable)
23
- *
24
- * This works because semver orders prereleases alphabetically:
25
- * dev.N < staging.N < release. A caret range starting at dev.0 naturally
26
- * upgrades through staging to production.
27
- */
28
- function phClintRange(version) {
29
- const match = /^(\d+\.\d+\.\d+)(?:-([a-z]+)\.\d+)?/.exec(version);
30
- if (!match)
31
- return `^${version}`;
32
- const base = match[1];
33
- const channel = match[2]; // "dev", "staging", or undefined
34
- return channel ? `^${base}-${channel}.0` : `^${base}`;
35
- }
36
- /** Version range for @powerhousedao/ph-clint{,-dev} deps in scaffolded projects. */
37
- const PH_CLINT_VERSION = phClintRange(CLI_VERSION);
38
- const POWERHOUSE_VERSION = '6.0.0-dev.170';
39
- export function buildCliPackageJson(spec) {
40
- const { mastra, powerhouse } = spec.features;
41
- const pkgName = powerhouse.enabled
42
- ? `${getPackageName(spec)}-cli`
43
- : getPackageName(spec);
44
- const bin = getBinName(spec);
45
- const dependencies = {
46
- '@powerhousedao/ph-clint': PH_CLINT_VERSION,
47
- zod: '^4.3.6',
48
- };
49
- if (mastra.enabled) {
50
- dependencies['@mastra/core'] = '^1.22.0';
51
- dependencies['@mastra/libsql'] = '^1.7.4';
52
- dependencies['@mastra/memory'] = '^1.13.1';
53
- }
54
- if (powerhouse.enabled) {
55
- dependencies[`${spec.name}-app`] = `file:../${spec.name}-app`;
56
- dependencies['@powerhousedao/reactor'] = POWERHOUSE_VERSION;
57
- dependencies['@powerhousedao/reactor-api'] = POWERHOUSE_VERSION;
58
- dependencies['@powerhousedao/shared'] = POWERHOUSE_VERSION;
59
- dependencies['document-model'] = POWERHOUSE_VERSION;
60
- }
61
- const scripts = {
62
- 'build:skills': 'tsx scripts/build-skills.ts',
63
- build: 'pnpm build:skills && tsc',
64
- dev: 'tsx src/main.ts',
65
- start: 'node dist/main.js',
66
- test: "NODE_OPTIONS='--experimental-vm-modules' jest --detectOpenHandles",
67
- lint: 'eslint src',
68
- };
69
- if (mastra.enabled) {
70
- scripts['mastra:dev'] = 'mastra dev';
71
- scripts['mastra:build'] = 'mastra build';
72
- scripts['mastra:start'] = 'mastra start';
73
- }
74
- const pkg = {
75
- name: pkgName,
76
- version: spec.version,
77
- private: true,
78
- type: 'module',
79
- };
80
- if (spec.description)
81
- pkg.description = spec.description;
82
- pkg.bin = { [bin]: './dist/main.js' };
83
- pkg.scripts = scripts;
84
- pkg.dependencies = dependencies;
85
- pkg.devDependencies = {
86
- '@jest/globals': '^30.2.0',
87
- '@types/node': '^25.5.2',
88
- jest: '^30.2.0',
89
- '@powerhousedao/ph-clint-dev': PH_CLINT_VERSION,
90
- 'ts-jest': '^29.4.6',
91
- tsx: '^4.19.0',
92
- typescript: '^6.0.2',
93
- };
94
- pkg.engines = { node: '>=22.13.0' };
95
- return JSON.stringify(pkg, null, 2) + '\n';
96
- }
1
+ export { buildCliPackageJson } from '@powerhousedao/ph-clint-dev/codegen/builders';
@@ -1,5 +1,17 @@
1
+ /**
2
+ * Builds `src/cli.ts` — the defineCli() call with feature blocks guarded by
3
+ * `@clint:begin`/`@clint:end` markers so the code generator can patch
4
+ * specific regions on subsequent runs (delta mode — future phase).
5
+ */
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
+ }
1
12
  export function buildCliTs(spec) {
2
13
  const { mastra, routine, powerhouse } = spec.features;
14
+ const ph = powerhouse;
3
15
  const lines = [];
4
16
  lines.push('/**');
5
17
  lines.push(' * CLI definition.');
@@ -8,32 +20,42 @@ export function buildCliTs(spec) {
8
20
  lines.push(' * markers are rewritten by ph-clint when the project spec changes.');
9
21
  lines.push(' * Everything outside the markers is user-editable and preserved.');
10
22
  lines.push(' */');
11
- if (powerhouse.enabled) {
12
- lines.push(`import path from 'node:path';`);
13
- lines.push(`import { defineCli, buildDefaultReactor } from '@powerhousedao/ph-clint';`);
14
- }
15
- else {
16
- lines.push(`import { defineCli } from '@powerhousedao/ph-clint';`);
23
+ const needsRoot = phAtLeast(ph, 'Reactor') || mastra.enabled;
24
+ lines.push('// @clint:begin imports');
25
+ const phClintImports = ['defineCli'];
26
+ if (phAtLeast(ph, 'Reactor'))
27
+ phClintImports.push('buildDefaultReactor');
28
+ // proxy has no additional imports
29
+ lines.push(`import { ${phClintImports.join(', ')} } from '@powerhousedao/ph-clint';`);
30
+ if (needsRoot) {
31
+ lines.push("import path from 'node:path';");
17
32
  }
18
- lines.push(`import { CLI_NAME, CLI_VERSION${powerhouse.enabled ? ', CLI_ROOT' : ''} } from './config.js';`);
33
+ lines.push(`import { CLI_NAME, CLI_VERSION${needsRoot ? ', CLI_ROOT' : ''} } from './config.js';`);
19
34
  lines.push(`import { configSchema, secretsSchema } from './framework.js';`);
20
- lines.push('');
21
- lines.push('// @clint:begin imports');
22
- if (powerhouse.enabled) {
23
- lines.push(`import { documentModels } from '${spec.name}-app';`);
35
+ if (phAtLeast(ph, 'Reactor')) {
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
+ }
24
42
  }
25
43
  if (mastra.enabled) {
26
44
  lines.push(`import { createAgent } from './agents/agent.js';`);
27
45
  }
46
+ if (mastra.enabled && mastra.common?.enableChat) {
47
+ lines.push(`import { chatSessionWatchTrigger } from '@powerhousedao/clint-common/chat';`);
48
+ }
28
49
  lines.push('// @clint:end imports');
29
50
  lines.push('');
30
- if (powerhouse.enabled) {
31
- lines.push(`const appDir = path.resolve(CLI_ROOT, '../${spec.name}-app');`);
32
- lines.push('');
33
- }
34
51
  lines.push('export const cli = defineCli({');
35
52
  lines.push(' name: CLI_NAME,');
36
53
  lines.push(' version: CLI_VERSION,');
54
+ lines.push(' // @clint:begin root');
55
+ if (phAtLeast(ph, 'Reactor')) {
56
+ lines.push(' root: CLI_ROOT,');
57
+ }
58
+ lines.push(' // @clint:end root');
37
59
  lines.push(' description: `${CLI_NAME} v${CLI_VERSION}`,');
38
60
  lines.push(' configSchema,');
39
61
  lines.push(' secretsSchema,');
@@ -47,8 +69,8 @@ export function buildCliTs(spec) {
47
69
  lines.push(' // @clint:end services');
48
70
  lines.push('');
49
71
  lines.push(' // @clint:begin triggers');
50
- if (routine.enabled) {
51
- lines.push(' triggers: [],');
72
+ if (mastra.enabled && mastra.common?.enableChat) {
73
+ lines.push(' triggers: [chatSessionWatchTrigger],');
52
74
  }
53
75
  else {
54
76
  lines.push(' triggers: [],');
@@ -57,8 +79,34 @@ export function buildCliTs(spec) {
57
79
  lines.push('');
58
80
  lines.push(' // @clint:begin prompts');
59
81
  lines.push(' prompts: {');
60
- lines.push(' sources: [],');
61
- lines.push(' agents: {},');
82
+ if (mastra.enabled) {
83
+ lines.push(" artifacts: [path.join(CLI_ROOT, 'gen', 'skills'), path.join(CLI_ROOT, 'dist', 'gen', 'skills')],");
84
+ }
85
+ else {
86
+ lines.push(' artifacts: [],');
87
+ }
88
+ if (mastra.enabled && mastra.agentId) {
89
+ lines.push(' agents: {');
90
+ lines.push(` '${mastra.agentId}': {`);
91
+ if (mastra.profiles.length > 0) {
92
+ lines.push(` name: '${mastra.profiles[0].id}',`);
93
+ lines.push(' sections: [');
94
+ for (const p of mastra.profiles) {
95
+ lines.push(` '${p.id}.md',`);
96
+ }
97
+ lines.push(' ],');
98
+ }
99
+ else {
100
+ lines.push(" name: 'AgentBase',");
101
+ lines.push(" sections: ['AgentBase.md'],");
102
+ }
103
+ lines.push(' skills: [],');
104
+ lines.push(' },');
105
+ lines.push(' },');
106
+ }
107
+ else {
108
+ lines.push(' agents: {},');
109
+ }
62
110
  lines.push(' skills: {},');
63
111
  lines.push(' },');
64
112
  lines.push(' // @clint:end prompts');
@@ -67,29 +115,24 @@ export function buildCliTs(spec) {
67
115
  lines.push(' events: {},');
68
116
  lines.push(' // @clint:end events');
69
117
  lines.push('');
118
+ lines.push(' // @clint:begin proxy');
119
+ if (spec.deployment.proxyEnabled) {
120
+ lines.push(' proxyEnabled: true,');
121
+ }
122
+ lines.push(' // @clint:end proxy');
123
+ lines.push('');
70
124
  lines.push(' // @clint:begin interactive');
71
125
  lines.push(' interactive: {');
72
- const ctxArgs = [];
73
- if (powerhouse.enabled && (powerhouse.switchboard || powerhouse.connect)) {
74
- ctxArgs.push('config');
75
- }
76
- ctxArgs.push('workdir');
77
- lines.push(` welcome: ({ ${ctxArgs.join(', ')} }) =>`);
126
+ lines.push(` welcome: ({ workdir }) =>`);
78
127
  lines.push(' [');
79
128
  lines.push(' `${CLI_NAME} v${CLI_VERSION}`,');
80
129
  lines.push(' `Workdir: ${workdir}`,');
81
- if (powerhouse.enabled && powerhouse.switchboard) {
82
- lines.push(' `Switchboard: http://localhost:${config.switchboardPort}`,');
83
- }
84
- if (powerhouse.enabled && powerhouse.connect) {
85
- lines.push(' `Connect: http://localhost:${config.connectPort}`,');
86
- }
87
130
  lines.push(" '',");
88
131
  if (mastra.enabled) {
89
- lines.push(" 'Type a message to talk to the agent, or /help for commands.',");
132
+ lines.push(" 'Type a message to talk to the agent, or / for commands.',");
90
133
  }
91
134
  else {
92
- lines.push(" 'Type /help for commands.',");
135
+ lines.push(" 'Type / for commands or /cli-docs for help.',");
93
136
  }
94
137
  lines.push(" ].join('\\n'),");
95
138
  lines.push(' },');
@@ -97,15 +140,23 @@ export function buildCliTs(spec) {
97
140
  lines.push('});');
98
141
  lines.push('');
99
142
  lines.push('// @clint:begin reactor');
100
- if (powerhouse.enabled) {
143
+ if (phAtLeast(ph, 'Reactor')) {
101
144
  lines.push('cli.configureReactor({');
102
145
  lines.push(' create: (ctx) =>');
103
146
  lines.push(' buildDefaultReactor(ctx, {');
104
- lines.push(' documentModels,');
147
+ const extPkgs = getExternalPackages(spec);
148
+ if (extPkgs.length === 0) {
149
+ lines.push(' documentModels,');
150
+ }
151
+ else {
152
+ const aliases = extPkgs.map((_, i) => extPkgs.length === 1 ? 'extModels' : `extModels${i}`);
153
+ lines.push(` documentModels: [...documentModels, ${aliases.map(a => `...${a}`).join(', ')}],`);
154
+ }
105
155
  lines.push(` drive: { name: '${spec.name}' },`);
156
+ lines.push(' subscriptions: {},');
106
157
  lines.push(' }),');
107
- lines.push(` switchboard: { enabled: ${String(powerhouse.switchboard)} },`);
108
- lines.push(` connect: { enabled: ${String(powerhouse.connect)}, workdir: appDir },`);
158
+ lines.push(` switchboard: { enabled: ${String(phAtLeast(ph, 'Switchboard'))} },`);
159
+ lines.push(` connect: { enabled: ${String(phAtLeast(ph, 'Connect'))} },`);
109
160
  lines.push('});');
110
161
  }
111
162
  lines.push('// @clint:end reactor');
@@ -5,4 +5,4 @@
5
5
  * can extend them without fighting the generator.
6
6
  */
7
7
  import { type ClintProjectSpec } from '../../spec/types.js';
8
- export declare function buildConfigTs(spec: ClintProjectSpec): string;
8
+ export declare function buildConfigTs(_spec: ClintProjectSpec): string;
@@ -1,17 +1,11 @@
1
- export function buildConfigTs(spec) {
2
- const hasCustomBin = !!spec.bin;
1
+ export function buildConfigTs(_spec) {
3
2
  const lines = [];
4
3
  lines.push(`import { readPackageInfo } from '@powerhousedao/ph-clint';`);
5
4
  lines.push('');
6
5
  lines.push('const pkg = readPackageInfo(import.meta.url);');
7
6
  lines.push('');
8
7
  lines.push('export const CLI_ROOT = pkg.root;');
9
- if (hasCustomBin) {
10
- lines.push(`export const CLI_NAME = '${spec.bin}';`);
11
- }
12
- else {
13
- lines.push(`export const CLI_NAME = pkg.name.replace(/-cli$/, '');`);
14
- }
8
+ lines.push(`export const CLI_NAME = pkg.name.replace(/-cli$/, '');`);
15
9
  lines.push('export const CLI_VERSION = pkg.version;');
16
10
  return lines.join('\n') + '\n';
17
11
  }