@powerhousedao/ph-clint-cli 0.1.0-dev.6 → 0.1.0-dev.61

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 +40 -10
  51. package/dist/commands/clint-project-init.js +55 -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 +133 -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 -12
  100. package/prompts/skills-ext/.gitkeep +0 -0
  101. package/prompts/skills-tpl/.gitkeep +0 -0
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Builds `src/agents/demo-agent.ts` — a deterministic echo agent fallback.
3
+ *
4
+ * Generated when `features.mastra.enabled` with full agent config so the real
5
+ * agent factory can fall back to demo mode when no API key is configured.
6
+ */
7
+ import { type ClintProjectSpec } from '../../spec/types.js';
8
+ export declare function buildDemoAgentTs(spec: ClintProjectSpec): string | null;
@@ -0,0 +1,50 @@
1
+ export function buildDemoAgentTs(spec) {
2
+ const { mastra } = spec.features;
3
+ // Only needed alongside the real agent (which imports it)
4
+ if (!mastra.enabled || !mastra.agentId || mastra.models.length === 0)
5
+ return null;
6
+ const agentId = mastra.agentId;
7
+ const agentName = mastra.agentName ?? agentId;
8
+ const agentDescription = mastra.agentDescription;
9
+ const agentImage = mastra.agentImage;
10
+ return [
11
+ "import type { AgentProvider, StreamChunk } from '@powerhousedao/ph-clint';",
12
+ '',
13
+ '/**',
14
+ ' * Demo agent — deterministic echo responses without an API key.',
15
+ ' *',
16
+ ' * Echoes user prompts with conversation tracking per thread.',
17
+ ' */',
18
+ 'export function createDemoAgent(): AgentProvider {',
19
+ ' const conversations = new Map<string, string[]>();',
20
+ '',
21
+ ' return {',
22
+ ` id: '${agentId}',`,
23
+ ` name: '${agentName}',`,
24
+ ...(agentDescription ? [` description: ${JSON.stringify(agentDescription)},`] : []),
25
+ ...(agentImage ? [` image: ${JSON.stringify(agentImage)},`] : []),
26
+ ' async *stream(prompt, opts) {',
27
+ " const threadId = opts?.threadId ?? 'default';",
28
+ ' if (!conversations.has(threadId)) {',
29
+ ' conversations.set(threadId, []);',
30
+ ' }',
31
+ ' const history = conversations.get(threadId)!;',
32
+ ' history.push(prompt);',
33
+ '',
34
+ ' const turnCount = history.length;',
35
+ ' if (turnCount > 1) {',
36
+ ' yield {',
37
+ " type: 'text-delta',",
38
+ ' text: `I understand you\'re continuing our conversation (turn ${turnCount}). `,',
39
+ ' } satisfies StreamChunk;',
40
+ ' }',
41
+ ' yield {',
42
+ " type: 'text-delta',",
43
+ ' text: `You said: "${prompt}". I\'m the demo agent — set an API key for real LLM responses.`,',
44
+ ' } satisfies StreamChunk;',
45
+ ' },',
46
+ ' };',
47
+ '}',
48
+ '',
49
+ ].join('\n');
50
+ }
@@ -1,4 +1,4 @@
1
1
  /**
2
- * Builds `eslint.config.js` for the CLI — placeholder flat config.
2
+ * Builds `eslint.config.js` for the CLI — minimal TypeScript-ESLint config.
3
3
  */
4
4
  export declare function buildEslintConfigJs(): string;
@@ -1,12 +1,15 @@
1
1
  /**
2
- * Builds `eslint.config.js` for the CLI — placeholder flat config.
2
+ * Builds `eslint.config.js` for the CLI — minimal TypeScript-ESLint config.
3
3
  */
4
4
  export function buildEslintConfigJs() {
5
5
  return [
6
6
  '// @clint:begin eslint',
7
- '// Placeholder ESLint flat config — replaced by codegen when the',
8
- "// project's lint stack is configured.",
9
- 'export default [];',
7
+ "import tseslint from 'typescript-eslint';",
8
+ '',
9
+ 'export default tseslint.config(',
10
+ ' tseslint.configs.recommended,',
11
+ " { ignores: ['dist/', 'gen/', 'coverage/'] },",
12
+ ');',
10
13
  '// @clint:end eslint',
11
14
  '',
12
15
  ].join('\n');
@@ -1,17 +1,22 @@
1
1
  /**
2
2
  * Builds `src/framework.gen.ts` — the fully machine-owned half of the
3
3
  * typed-binding split. Regenerated on every `init` and `update`; holds the
4
- * `defineRegistry([...] as const)` call that describes which document models
4
+ * `defineRegistry([...])` call that describes which document models
5
5
  * are bound into `framework.ts`'s typed factories.
6
6
  *
7
- * Kept deliberately small: this file exports only `registry` and the
8
- * `Registry` type. The `createTypes` call lives in `framework.ts` (the
9
- * user-owned half) so `configSchema` edits stay local and we avoid an import
10
- * cycle between the two files.
7
+ * Iterates all packages' document types. The app package's modules are
8
+ * imported from the local `{name}-app` package; external packages' modules
9
+ * are imported from their npm package name.
10
+ *
11
+ * Document type entries may be explicit IDs (`powerhouse/ph-clint-project`)
12
+ * or glob patterns (`*​/*`, `powerhouse/*`, `acme/doc-*`). Explicit IDs
13
+ * produce static named imports; glob patterns import the package's
14
+ * `documentModels` array and filter at runtime so newly-added document
15
+ * models are picked up without a codegen re-run.
11
16
  *
12
17
  * Emitted only when Powerhouse is enabled — flat-layout impls have no
13
18
  * reactor package to import modules from and bind `createTypes` directly in
14
- * `framework.ts`. When Powerhouse is on but no `documentTypes` are declared,
19
+ * `framework.ts`. When Powerhouse is on but no document types are declared,
15
20
  * we still emit this file with an empty `defineRegistry([])` so impl code's
16
21
  * `import { registry } from './framework.gen.js'` keeps resolving across
17
22
  * regens.
@@ -1,34 +1,64 @@
1
1
  /**
2
2
  * Builds `src/framework.gen.ts` — the fully machine-owned half of the
3
3
  * typed-binding split. Regenerated on every `init` and `update`; holds the
4
- * `defineRegistry([...] as const)` call that describes which document models
4
+ * `defineRegistry([...])` call that describes which document models
5
5
  * are bound into `framework.ts`'s typed factories.
6
6
  *
7
- * Kept deliberately small: this file exports only `registry` and the
8
- * `Registry` type. The `createTypes` call lives in `framework.ts` (the
9
- * user-owned half) so `configSchema` edits stay local and we avoid an import
10
- * cycle between the two files.
7
+ * Iterates all packages' document types. The app package's modules are
8
+ * imported from the local `{name}-app` package; external packages' modules
9
+ * are imported from their npm package name.
10
+ *
11
+ * Document type entries may be explicit IDs (`powerhouse/ph-clint-project`)
12
+ * or glob patterns (`*​/*`, `powerhouse/*`, `acme/doc-*`). Explicit IDs
13
+ * produce static named imports; glob patterns import the package's
14
+ * `documentModels` array and filter at runtime so newly-added document
15
+ * models are picked up without a codegen re-run.
11
16
  *
12
17
  * Emitted only when Powerhouse is enabled — flat-layout impls have no
13
18
  * reactor package to import modules from and bind `createTypes` directly in
14
- * `framework.ts`. When Powerhouse is on but no `documentTypes` are declared,
19
+ * `framework.ts`. When Powerhouse is on but no document types are declared,
15
20
  * we still emit this file with an empty `defineRegistry([])` so impl code's
16
21
  * `import { registry } from './framework.gen.js'` keeps resolving across
17
22
  * regens.
18
23
  */
19
- import { getDocumentTypeModuleName, } from '../../spec/types.js';
20
- /** Local package name of the reactor package for this project. */
21
- function appPackageName(spec) {
22
- return `${spec.name}-app`;
23
- }
24
+ import { docTypeGlobToRegex, getAppPackageName, getDocumentTypeModuleName, getDocumentTypeSlug, isDocTypeGlob, phAtLeast, } from '../../spec/types.js';
24
25
  export function buildFrameworkGenTs(spec) {
25
- if (!spec.features.powerhouse.enabled)
26
+ if (!phAtLeast(spec.features.powerhouse, 'Reactor'))
26
27
  return null;
27
- const pkg = appPackageName(spec);
28
- const entries = spec.documentTypes.map((docType) => ({
29
- docType,
30
- name: getDocumentTypeModuleName(docType),
31
- }));
28
+ const appPkg = getAppPackageName(spec);
29
+ // Collect entries across packages. Each package may contribute both
30
+ // explicit named imports and glob-based runtime filters.
31
+ const entries = [];
32
+ let globCounter = 0;
33
+ for (const pkg of spec.packages) {
34
+ const isApp = pkg.packageName === appPkg;
35
+ // Collect glob patterns for this package (may be multiple).
36
+ const globs = pkg.documentTypes.filter(isDocTypeGlob);
37
+ const explicits = pkg.documentTypes.filter((dt) => !isDocTypeGlob(dt));
38
+ for (const docType of explicits) {
39
+ const slug = getDocumentTypeSlug(docType);
40
+ entries.push({
41
+ kind: 'explicit',
42
+ name: getDocumentTypeModuleName(docType),
43
+ importFrom: isApp ? appPkg : `${pkg.packageName}/document-models/${slug}`,
44
+ });
45
+ }
46
+ if (globs.length > 0) {
47
+ // Merge all globs for this package into a single regex alternation.
48
+ const combined = globs.length === 1
49
+ ? docTypeGlobToRegex(globs[0])
50
+ : globs.map((g) => `(?:${docTypeGlobToRegex(g)})`).join('|');
51
+ const alias = globCounter === 0 ? 'globModels' : `globModels${globCounter}`;
52
+ globCounter++;
53
+ entries.push({
54
+ kind: 'glob',
55
+ modelsAlias: alias,
56
+ importFrom: isApp ? appPkg : pkg.packageName,
57
+ regexSource: combined,
58
+ });
59
+ }
60
+ }
61
+ const hasGlobs = entries.some((e) => e.kind === 'glob');
32
62
  const lines = [];
33
63
  lines.push('/**');
34
64
  lines.push(' * THIS FILE IS GENERATED BY ph-clint-cli. DO NOT EDIT.');
@@ -38,24 +68,46 @@ export function buildFrameworkGenTs(spec) {
38
68
  lines.push(' * this file will be overwritten.');
39
69
  lines.push(' */');
40
70
  lines.push(`import { defineRegistry } from '@powerhousedao/ph-clint';`);
71
+ // Emit imports — named imports for explicit entries, documentModels for globs.
41
72
  for (const e of entries) {
42
- lines.push(`import { ${e.name} } from '${pkg}';`);
73
+ if (e.kind === 'explicit') {
74
+ lines.push(`import { ${e.name} } from '${e.importFrom}';`);
75
+ }
76
+ else {
77
+ lines.push(`import { documentModels as ${e.modelsAlias} } from '${e.importFrom}';`);
78
+ }
43
79
  }
44
80
  lines.push('');
45
81
  lines.push('/**');
46
82
  lines.push(' * Typed document registry derived from the reactor package\'s document models.');
47
- lines.push(' * Regenerated whenever the spec\'s `documentTypes` list changes.');
83
+ lines.push(' * Regenerated whenever the spec\'s packages or document types change.');
48
84
  lines.push(' */');
49
85
  if (entries.length === 0) {
50
86
  lines.push('export const registry = defineRegistry([] as const);');
51
87
  }
52
- else {
88
+ else if (!hasGlobs) {
89
+ // Pure explicit — use `as const` for full type inference.
53
90
  lines.push('export const registry = defineRegistry([');
54
91
  for (const e of entries) {
55
- lines.push(` ${e.name},`);
92
+ if (e.kind === 'explicit') {
93
+ lines.push(` ${e.name},`);
94
+ }
56
95
  }
57
96
  lines.push('] as const);');
58
97
  }
98
+ else {
99
+ // Mix of explicit + glob — runtime filter loses `as const` inference.
100
+ lines.push('export const registry = defineRegistry([');
101
+ for (const e of entries) {
102
+ if (e.kind === 'explicit') {
103
+ lines.push(` ${e.name},`);
104
+ }
105
+ else {
106
+ lines.push(` ...${e.modelsAlias}.filter((m) => /${e.regexSource}/.test(m.documentModel.global.id)),`);
107
+ }
108
+ }
109
+ lines.push(']);');
110
+ }
59
111
  lines.push('');
60
112
  lines.push('export type Registry = typeof registry;');
61
113
  return lines.join('\n') + '\n';
@@ -1,6 +1,26 @@
1
+ /**
2
+ * Builds `src/framework.ts` — the user-owned half of the typed-binding split.
3
+ *
4
+ * Emitted **only on create**. Once the file exists, codegen never overwrites
5
+ * it: users are expected to extend `configSchema` and `secretsSchema` here,
6
+ * and those edits must survive regens.
7
+ *
8
+ * Behavior differs by layout:
9
+ *
10
+ * - **Powerhouse enabled** — this file declares `configSchema`/`secretsSchema`
11
+ * and re-exports `registry`, `defineCommand`, `defineTrigger`,
12
+ * `defineService`, and `createDocumentChangeTrigger` from the companion
13
+ * `framework.gen.ts`. Adding a document type to the spec regenerates
14
+ * `framework.gen.ts`; this file keeps resolving its re-exports unchanged.
15
+ *
16
+ * - **Powerhouse disabled** — no reactor package exists to register modules
17
+ * against, so this file binds `createTypes({ configSchema })` directly and
18
+ * exports the typed factories from here. No `framework.gen.ts` is emitted.
19
+ */
20
+ import { phAtLeast } from '../../spec/types.js';
1
21
  export function buildFrameworkTs(spec) {
2
22
  const { mastra, powerhouse } = spec.features;
3
- const hasGen = powerhouse.enabled;
23
+ const hasGen = phAtLeast(powerhouse, 'Reactor');
4
24
  const lines = [];
5
25
  lines.push('/**');
6
26
  lines.push(' * Per-CLI typed framework binding.');
@@ -22,24 +42,30 @@ export function buildFrameworkTs(spec) {
22
42
  }
23
43
  lines.push('');
24
44
  lines.push('export const configSchema = z.object({');
45
+ lines.push(' // @clint:begin framework-config');
25
46
  if (mastra.enabled) {
26
- lines.push(" model: z.string().default('anthropic/claude-haiku-4-5').describe('LLM model to use'),");
47
+ const defaultModel = mastra.models.find(m => m.isDefault)?.id ?? 'anthropic/claude-sonnet-4-5';
48
+ lines.push(` model: z.string().default('${defaultModel}').describe('LLM model to use'),`, ` agentLogging: z.boolean().default(false).describe('Enable agent conversation logging'),`);
27
49
  }
28
- // Ports are derived from CLI name by resolveReactorDefaults() — no config fields needed.
29
- // Override via switchboard.port / connect.port in configureReactor() if required.
30
- lines.push(' // Add your own config fields here — this file survives regens.');
50
+ lines.push(' // @clint:end framework-config');
31
51
  lines.push('});');
32
52
  lines.push('');
33
53
  lines.push('export const secretsSchema = z.object({');
54
+ lines.push(' // @clint:begin framework-secrets');
34
55
  if (mastra.enabled) {
35
- lines.push(" apiKey: z.string().optional().describe('LLM API key'),");
56
+ const providers = [...new Set(mastra.models.map(m => m.id.split(/[:/]/)[0]))];
57
+ for (const provider of providers) {
58
+ const field = `${provider}ApiKey`;
59
+ lines.push(` ${field}: z.string().optional().describe('${provider} API key'),`);
60
+ }
36
61
  }
62
+ lines.push(' // @clint:end framework-secrets');
37
63
  lines.push('});');
38
64
  lines.push('');
39
65
  lines.push('export type Config = z.infer<typeof configSchema> &');
40
66
  lines.push(' z.infer<typeof secretsSchema>;');
41
67
  lines.push('');
42
- lines.push('const fullConfigSchema = configSchema.merge(secretsSchema);');
68
+ lines.push('const fullConfigSchema = configSchema.extend(secretsSchema.shape);');
43
69
  lines.push('');
44
70
  if (hasGen) {
45
71
  lines.push('export const {');
@@ -1,44 +1 @@
1
- /**
2
- * Registry of file builders. Each entry knows its own relative path (within
3
- * the CLI sub-tree) and a function that builds its content from the spec.
4
- *
5
- * Orchestrated by `codegen/index.ts` — it walks this registry, adjusts paths
6
- * for flat vs split layouts, and writes the files.
7
- */
8
- import { buildCliPackageJson } from './cli-package-json.js';
9
- import { buildCliTs } from './cli-ts.js';
10
- import { buildConfigTs } from './config-ts.js';
11
- import { buildMainTs } from './main-ts.js';
12
- import { buildTsconfigJson } from './tsconfig-json.js';
13
- import { buildJestConfigJs } from './jest-config-js.js';
14
- import { buildEslintConfigJs } from './eslint-config-js.js';
15
- import { buildGitignore } from './gitignore.js';
16
- import { buildMastraIndexTs } from './mastra-index-ts.js';
17
- import { buildBuildSkillsScript } from './build-skills-ts.js';
18
- import { buildAgentBaseMd } from './agent-base-md.js';
19
- import { buildAgentTs } from './agent-ts.js';
20
- import { buildFrameworkGenTs } from './framework-gen-ts.js';
21
- import { buildFrameworkTs } from './framework-ts.js';
22
- import { type ClintProjectSpec } from '../../spec/types.js';
23
- /**
24
- * A spec-driven file builder. Returns `null` from `build` to indicate the
25
- * file should not be emitted for the given spec.
26
- */
27
- export interface FileBuilder {
28
- /** Path relative to the CLI root (flat or `{name}-cli/`). */
29
- relativePath: string;
30
- build(spec: ClintProjectSpec): string | null;
31
- /**
32
- * When true, this file is only emitted on `mode: 'create'`. In `update`
33
- * mode the planner ignores the builder entirely, leaving any on-disk
34
- * version untouched regardless of hash state. Used for files that carry
35
- * user-owned hand edits (e.g. `src/framework.ts`'s `configSchema`).
36
- */
37
- initOnly?: boolean;
38
- }
39
- export declare const CLI_FILE_BUILDERS: FileBuilder[];
40
- export { buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildFrameworkGenTs, buildFrameworkTs, };
41
- export { buildRootPackageJson } from './root-package-json.js';
42
- export { buildPublishConfigTs } from './publish-config-ts.js';
43
- export { buildReadme } from './readme-md.js';
44
- export { buildAppIndexTs } from './app-index-ts.js';
1
+ export { type FileBuilder, CLI_FILE_BUILDERS, getProfileFileBuilders, buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildDemoAgentTs, buildFrameworkGenTs, buildFrameworkTs, buildManifestJson, buildSmokeTestTs, buildRootPackageJson, buildPublishConfigJs, buildReadme, buildAppIndexTs, } from '@powerhousedao/ph-clint-dev/codegen/builders';
@@ -1,61 +1 @@
1
- /**
2
- * Registry of file builders. Each entry knows its own relative path (within
3
- * the CLI sub-tree) and a function that builds its content from the spec.
4
- *
5
- * Orchestrated by `codegen/index.ts` — it walks this registry, adjusts paths
6
- * for flat vs split layouts, and writes the files.
7
- */
8
- import { buildCliPackageJson } from './cli-package-json.js';
9
- import { buildCliTs } from './cli-ts.js';
10
- import { buildConfigTs } from './config-ts.js';
11
- import { buildMainTs } from './main-ts.js';
12
- import { buildTsconfigJson } from './tsconfig-json.js';
13
- import { buildJestConfigJs } from './jest-config-js.js';
14
- import { buildEslintConfigJs } from './eslint-config-js.js';
15
- import { buildGitignore } from './gitignore.js';
16
- import { buildMastraIndexTs } from './mastra-index-ts.js';
17
- import { buildBuildSkillsScript } from './build-skills-ts.js';
18
- import { buildAgentBaseMd } from './agent-base-md.js';
19
- import { buildAgentTs } from './agent-ts.js';
20
- import { buildFrameworkGenTs } from './framework-gen-ts.js';
21
- import { buildFrameworkTs } from './framework-ts.js';
22
- export const CLI_FILE_BUILDERS = [
23
- { relativePath: 'package.json', build: buildCliPackageJson },
24
- { relativePath: 'tsconfig.json', build: () => buildTsconfigJson() },
25
- { relativePath: 'jest.config.js', build: () => buildJestConfigJs() },
26
- { relativePath: 'eslint.config.js', build: () => buildEslintConfigJs() },
27
- { relativePath: '.gitignore', build: () => buildGitignore() },
28
- { relativePath: 'src/main.ts', build: () => buildMainTs() },
29
- { relativePath: 'src/cli.ts', build: buildCliTs },
30
- { relativePath: 'src/config.ts', build: buildConfigTs },
31
- // User-owned; init-only. Holds `configSchema` + `secretsSchema` edits.
32
- { relativePath: 'src/framework.ts', build: buildFrameworkTs, initOnly: true },
33
- // Machine-owned; regenerated on every run. Null when no document types.
34
- { relativePath: 'src/framework.gen.ts', build: buildFrameworkGenTs },
35
- { relativePath: 'src/mastra/index.ts', build: buildMastraIndexTs },
36
- { relativePath: 'scripts/build-skills.ts', build: () => buildBuildSkillsScript() },
37
- { relativePath: 'prompts/agent-profiles/AgentBase.md', build: buildAgentBaseMd },
38
- {
39
- relativePath: 'src/agents/agent.ts',
40
- build: (spec) => (spec.features.mastra.enabled ? buildAgentTs(spec) : null),
41
- },
42
- // Gitkeep placeholders so directories are tracked in git when otherwise empty.
43
- { relativePath: 'src/commands/.gitkeep', build: () => '' },
44
- { relativePath: 'src/services/.gitkeep', build: () => '' },
45
- {
46
- relativePath: 'src/triggers/.gitkeep',
47
- build: (spec) => (spec.features.routine.enabled ? '' : ''),
48
- },
49
- {
50
- relativePath: 'src/agents/.gitkeep',
51
- build: (spec) => (spec.features.mastra.enabled ? null : ''),
52
- },
53
- { relativePath: 'prompts/skills-tpl/.gitkeep', build: () => '' },
54
- { relativePath: 'prompts/skills-ext/.gitkeep', build: () => '' },
55
- { relativePath: 'tests/.gitkeep', build: () => '' },
56
- ];
57
- export { buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildFrameworkGenTs, buildFrameworkTs, };
58
- export { buildRootPackageJson } from './root-package-json.js';
59
- export { buildPublishConfigTs } from './publish-config-ts.js';
60
- export { buildReadme } from './readme-md.js';
61
- export { buildAppIndexTs } from './app-index-ts.js';
1
+ export { CLI_FILE_BUILDERS, getProfileFileBuilders, buildCliPackageJson, buildCliTs, buildConfigTs, buildMainTs, buildTsconfigJson, buildJestConfigJs, buildEslintConfigJs, buildGitignore, buildMastraIndexTs, buildBuildSkillsScript, buildAgentBaseMd, buildAgentTs, buildDemoAgentTs, buildFrameworkGenTs, buildFrameworkTs, buildManifestJson, buildSmokeTestTs, buildRootPackageJson, buildPublishConfigJs, buildReadme, buildAppIndexTs, } from '@powerhousedao/ph-clint-dev/codegen/builders';
@@ -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
+ proxyEnabled: spec.deployment.proxyEnabled,
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
- // When Mastra is enabled but we still emit the demo `AgentProvider` shim
16
- // (not a real `@mastra/core` Agent), there is no `mastra` export yet —
17
- // `mastra dev` will surface a helpful message once you wire a real Agent.
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,33 @@
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, getBinName, getAppFolderName, getCliFolderName, } 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 binName = getBinName(spec);
14
+ const packages = split
15
+ ? `[
16
+ { path: '${getAppFolderName(spec)}', category: 'app' },
17
+ { path: '${getCliFolderName(spec)}', category: 'cli' },
18
+ ]`
19
+ : `[
20
+ { path: '.', category: 'cli' },
21
+ ]`;
22
+ return `// Publish config — loaded by ph-clint's publish pipeline.
23
+ // definePublishConfig is an identity function; a plain export is equivalent.
24
+ export default {
25
+ groups: {
26
+ '${binName}': {
27
+ version: '${baseVersion}',
28
+ packages: ${packages},
29
+ },
30
+ },
31
+ };
32
+ `;
33
+ }
@@ -1,6 +1,8 @@
1
1
  /**
2
- * Builds the root `publish.config.ts` for split-layout projects.
3
- * Defines a single lockstep group containing both the app and cli packages.
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 `.`.
4
6
  */
5
7
  import { type ClintProjectSpec } from '../../spec/types.js';
6
8
  export declare function buildPublishConfigTs(spec: ClintProjectSpec): string;