@powerhousedao/ph-clint-cli 0.1.0-dev.0
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/README.md +84 -0
- package/dist/agents/clint-agent.d.ts +12 -0
- package/dist/agents/clint-agent.js +42 -0
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +79 -0
- package/dist/codegen/builders/agent-base-md.d.ts +5 -0
- package/dist/codegen/builders/agent-base-md.js +18 -0
- package/dist/codegen/builders/agent-ts.d.ts +9 -0
- package/dist/codegen/builders/agent-ts.js +34 -0
- package/dist/codegen/builders/app-index-ts.d.ts +18 -0
- package/dist/codegen/builders/app-index-ts.js +33 -0
- package/dist/codegen/builders/build-skills-ts.d.ts +4 -0
- package/dist/codegen/builders/build-skills-ts.js +37 -0
- package/dist/codegen/builders/cli-package-json.d.ts +8 -0
- package/dist/codegen/builders/cli-package-json.js +69 -0
- package/dist/codegen/builders/cli-ts.d.ts +7 -0
- package/dist/codegen/builders/cli-ts.js +110 -0
- package/dist/codegen/builders/config-ts.d.ts +8 -0
- package/dist/codegen/builders/config-ts.js +21 -0
- package/dist/codegen/builders/eslint-config-js.d.ts +4 -0
- package/dist/codegen/builders/eslint-config-js.js +13 -0
- package/dist/codegen/builders/framework-gen-ts.d.ts +20 -0
- package/dist/codegen/builders/framework-gen-ts.js +62 -0
- package/dist/codegen/builders/framework-ts.d.ts +21 -0
- package/dist/codegen/builders/framework-ts.js +74 -0
- package/dist/codegen/builders/gitignore.d.ts +4 -0
- package/dist/codegen/builders/gitignore.js +18 -0
- package/dist/codegen/builders/index.d.ts +43 -0
- package/dist/codegen/builders/index.js +60 -0
- package/dist/codegen/builders/jest-config-js.d.ts +4 -0
- package/dist/codegen/builders/jest-config-js.js +19 -0
- package/dist/codegen/builders/main-ts.d.ts +5 -0
- package/dist/codegen/builders/main-ts.js +13 -0
- package/dist/codegen/builders/mastra-index-ts.d.ts +8 -0
- package/dist/codegen/builders/mastra-index-ts.js +30 -0
- package/dist/codegen/builders/readme-md.d.ts +5 -0
- package/dist/codegen/builders/readme-md.js +44 -0
- package/dist/codegen/builders/root-package-json.d.ts +7 -0
- package/dist/codegen/builders/root-package-json.js +27 -0
- package/dist/codegen/builders/tsconfig-json.d.ts +4 -0
- package/dist/codegen/builders/tsconfig-json.js +22 -0
- package/dist/codegen/exec.d.ts +20 -0
- package/dist/codegen/exec.js +41 -0
- package/dist/codegen/hashes.d.ts +6 -0
- package/dist/codegen/hashes.js +60 -0
- package/dist/codegen/index.d.ts +39 -0
- package/dist/codegen/index.js +292 -0
- package/dist/codegen/markers.d.ts +36 -0
- package/dist/codegen/markers.js +86 -0
- package/dist/codegen/migrate/flat-to-split.d.ts +15 -0
- package/dist/codegen/migrate/flat-to-split.js +119 -0
- package/dist/codegen/scaffold.d.ts +34 -0
- package/dist/codegen/scaffold.js +60 -0
- package/dist/codegen/write.d.ts +6 -0
- package/dist/codegen/write.js +32 -0
- package/dist/commands/init.d.ts +57 -0
- package/dist/commands/init.js +168 -0
- package/dist/commands/regen.d.ts +18 -0
- package/dist/commands/regen.js +68 -0
- package/dist/config.d.ts +5 -0
- package/dist/config.js +7 -0
- package/dist/framework.d.ts +239 -0
- package/dist/framework.gen.d.ts +37 -0
- package/dist/framework.gen.js +16 -0
- package/dist/framework.js +41 -0
- package/dist/main.d.ts +2 -0
- package/dist/main.js +3 -0
- package/dist/mastra/index.d.ts +10 -0
- package/dist/mastra/index.js +11 -0
- package/dist/spec/file.d.ts +4 -0
- package/dist/spec/file.js +34 -0
- package/dist/spec/from-document.d.ts +18 -0
- package/dist/spec/from-document.js +30 -0
- package/dist/spec/types.d.ts +62 -0
- package/dist/spec/types.js +112 -0
- package/dist/triggers/spec-change.d.ts +43 -0
- package/dist/triggers/spec-change.js +171 -0
- package/package.json +60 -0
- package/prompts/agent-profiles/AgentBase.md +13 -0
- package/prompts/skills-ext/.gitkeep +0 -0
- package/prompts/skills-tpl/.gitkeep +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# ph-clint-tpl-cli
|
|
2
|
+
|
|
3
|
+
Template for the **ph-clint CLI side** of an implementation project. Starts
|
|
4
|
+
as a flat layout (no Powerhouse reactor-package alongside it). When the
|
|
5
|
+
`powerhouse` feature gets toggled on, the generator performs a one-time
|
|
6
|
+
migration that moves this tree into `{name}-cli/` and scaffolds a sibling
|
|
7
|
+
`{name}-app/`.
|
|
8
|
+
|
|
9
|
+
## Folder layout
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
cli/
|
|
13
|
+
├── src/
|
|
14
|
+
│ ├── main.ts # bin entrypoint (cli.run(process.argv))
|
|
15
|
+
│ ├── cli.ts # defineCli(...) call with @clint markers
|
|
16
|
+
│ ├── config.ts # configSchema + secretsSchema
|
|
17
|
+
│ ├── mastra/ # Mastra Studio entry (populated when Mastra is on)
|
|
18
|
+
│ ├── agents/ # Mastra agent definitions
|
|
19
|
+
│ ├── commands/ # defineCommand(...) definitions
|
|
20
|
+
│ ├── services/ # defineService(...) definitions
|
|
21
|
+
│ └── triggers/ # defineTrigger(...) definitions
|
|
22
|
+
├── prompts/ # Handlebars source for agent profiles & skills
|
|
23
|
+
│ ├── agent-profiles/ # AgentBase.md + specialized profiles
|
|
24
|
+
│ ├── skills-tpl/ # skill templates (authored here)
|
|
25
|
+
│ └── skills-ext/ # external/pre-built skills (dropped in as-is)
|
|
26
|
+
├── scripts/
|
|
27
|
+
│ └── build-skills.ts # compiles prompts/ → gen/ via ph-clint-dev
|
|
28
|
+
├── gen/ # codegen output (gitignored; built at build:skills)
|
|
29
|
+
└── tests/ # user-authored tests
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Feature toggles
|
|
33
|
+
|
|
34
|
+
Three independently togglable features. Each one is a `@clint:begin {name}`
|
|
35
|
+
/ `@clint:end {name}` region that `ts-morph` can rewrite:
|
|
36
|
+
|
|
37
|
+
### `powerhouse`
|
|
38
|
+
|
|
39
|
+
Enables the Powerhouse Reactor stack (Reactor, optional Switchboard,
|
|
40
|
+
optional Connect). On first enablement, the generator performs a one-time
|
|
41
|
+
migration:
|
|
42
|
+
|
|
43
|
+
1. Moves every file from `{root}/` to `{root}/{name}-cli/`.
|
|
44
|
+
2. Runs `ph init` inside `{root}/{name}-app/` to scaffold the standard
|
|
45
|
+
Powerhouse reactor-package layout.
|
|
46
|
+
3. Writes a new root `package.json` with passthrough scripts (no pnpm
|
|
47
|
+
workspaces — they interfere with `{name}-app`'s own builds).
|
|
48
|
+
|
|
49
|
+
### `mastra`
|
|
50
|
+
|
|
51
|
+
Enables the Mastra AI agent stack — agent definitions, thread-based memory
|
|
52
|
+
(LibSQL), optional MCP client, and the Mastra Studio entry point at
|
|
53
|
+
`src/mastra/index.ts` so `mastra dev` / `mastra build` / `mastra start` work.
|
|
54
|
+
|
|
55
|
+
### `routine`
|
|
56
|
+
|
|
57
|
+
Enables the tick-based routine loop and trigger registration. Forced on
|
|
58
|
+
when `mastra` is enabled (an agent without a routine can still run from the
|
|
59
|
+
REPL, but most useful setups want the loop).
|
|
60
|
+
|
|
61
|
+
## Codegen markers
|
|
62
|
+
|
|
63
|
+
Regions the generator can rewrite look like:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// src/cli.ts
|
|
67
|
+
export const cli = defineCli({
|
|
68
|
+
// @clint:begin commands
|
|
69
|
+
commands: [/* list injected by codegen */],
|
|
70
|
+
// @clint:end commands
|
|
71
|
+
|
|
72
|
+
// @clint:begin services
|
|
73
|
+
services: [/* list injected by codegen */],
|
|
74
|
+
// @clint:end services
|
|
75
|
+
});
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Everything *outside* the markers is user-editable and preserved across
|
|
79
|
+
regenerations. Everything *inside* a `@clint:begin`/`@clint:end` pair is
|
|
80
|
+
codegen-owned.
|
|
81
|
+
|
|
82
|
+
Files under `gen/` are fully codegen-owned — wiped and rewritten on every
|
|
83
|
+
`build:skills`. Everything in `src/` is human-owned except for the
|
|
84
|
+
explicitly marked regions.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentProvider, AgentSetupContext } from '@powerhousedao/ph-clint';
|
|
2
|
+
import type { Config } from '../framework.js';
|
|
3
|
+
export declare const AGENT_ID = "clint";
|
|
4
|
+
/**
|
|
5
|
+
* Agent factory for the ph-clint CLI.
|
|
6
|
+
*
|
|
7
|
+
* Demo mode echoes prompts; with an API key set via PH_CLINT_API_KEY, builds
|
|
8
|
+
* a full Mastra agent. The Powerhouse integration is still in scope but the
|
|
9
|
+
* agent does not yet write to any document model (document models land in
|
|
10
|
+
* Phase 4).
|
|
11
|
+
*/
|
|
12
|
+
export declare function createAgent(ctx: AgentSetupContext<Config>): Promise<AgentProvider>;
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export const AGENT_ID = 'clint';
|
|
2
|
+
const instructions = `You are Clint — a ph-clint assistant that helps users scaffold, configure, and maintain ph-clint implementation projects.
|
|
3
|
+
|
|
4
|
+
## Behavior
|
|
5
|
+
- Be concise and practical.
|
|
6
|
+
- When the user asks about a project, inspect the ClintProjectSpecification document via the Powerhouse Reactor when available.
|
|
7
|
+
- Prefer small, incremental changes to the project's spec document over direct file edits.`;
|
|
8
|
+
/**
|
|
9
|
+
* Agent factory for the ph-clint CLI.
|
|
10
|
+
*
|
|
11
|
+
* Demo mode echoes prompts; with an API key set via PH_CLINT_API_KEY, builds
|
|
12
|
+
* a full Mastra agent. The Powerhouse integration is still in scope but the
|
|
13
|
+
* agent does not yet write to any document model (document models land in
|
|
14
|
+
* Phase 4).
|
|
15
|
+
*/
|
|
16
|
+
export async function createAgent(ctx) {
|
|
17
|
+
if (!ctx.config.apiKey)
|
|
18
|
+
return createDemoAgent();
|
|
19
|
+
const { createMastraHelpers } = await import('@powerhousedao/ph-clint/mastra');
|
|
20
|
+
const { Agent } = await import('@mastra/core/agent');
|
|
21
|
+
const m = createMastraHelpers(ctx);
|
|
22
|
+
const mastraAgent = new Agent({
|
|
23
|
+
id: AGENT_ID,
|
|
24
|
+
name: 'Clint',
|
|
25
|
+
instructions,
|
|
26
|
+
model: { id: ctx.config.model, apiKey: ctx.config.apiKey },
|
|
27
|
+
tools: await m.getTools(),
|
|
28
|
+
memory: await m.createMemory(),
|
|
29
|
+
});
|
|
30
|
+
return m.wrapAgent(mastraAgent, { maxSteps: 40 });
|
|
31
|
+
}
|
|
32
|
+
function createDemoAgent() {
|
|
33
|
+
return {
|
|
34
|
+
id: AGENT_ID,
|
|
35
|
+
async *stream(prompt) {
|
|
36
|
+
yield {
|
|
37
|
+
type: 'text-delta',
|
|
38
|
+
text: `[Clint demo mode — set PH_CLINT_API_KEY for real LLM responses]\n\nYou said: "${prompt}"\n`,
|
|
39
|
+
};
|
|
40
|
+
},
|
|
41
|
+
};
|
|
42
|
+
}
|
package/dist/cli.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const cli: import("@powerhousedao/ph-clint").Cli;
|
package/dist/cli.js
ADDED
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ph-clint CLI definition.
|
|
3
|
+
*
|
|
4
|
+
* This file is the codegen anchor point. Regions bracketed by
|
|
5
|
+
* `@clint:begin {name}` / `@clint:end {name}` comment markers are
|
|
6
|
+
* rewritten by ph-clint-cli's generator when the project spec changes.
|
|
7
|
+
* Everything outside the markers is user-editable and preserved.
|
|
8
|
+
*/
|
|
9
|
+
import path from 'node:path';
|
|
10
|
+
import { fileURLToPath } from 'node:url';
|
|
11
|
+
import { defineCli, buildDefaultReactor } from '@powerhousedao/ph-clint';
|
|
12
|
+
import { CLI_NAME, CLI_VERSION } from './config.js';
|
|
13
|
+
import { configSchema, secretsSchema } from './framework.js';
|
|
14
|
+
// @clint:begin imports
|
|
15
|
+
import { documentModels } from '@powerhousedao/ph-clint-app';
|
|
16
|
+
import { createAgent } from './agents/clint-agent.js';
|
|
17
|
+
import { init } from './commands/init.js';
|
|
18
|
+
import { regen } from './commands/regen.js';
|
|
19
|
+
import { specChangeTrigger } from './triggers/spec-change.js';
|
|
20
|
+
// @clint:end imports
|
|
21
|
+
// Connect (ph connect) must run inside the Reactor Package (ph-clint-app).
|
|
22
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
23
|
+
const appDir = path.resolve(__dirname, '../../ph-clint-app');
|
|
24
|
+
export const cli = defineCli({
|
|
25
|
+
name: CLI_NAME,
|
|
26
|
+
version: CLI_VERSION,
|
|
27
|
+
description: `${CLI_NAME} v${CLI_VERSION} — scaffold and maintain ph-clint implementation projects`,
|
|
28
|
+
configSchema,
|
|
29
|
+
secretsSchema,
|
|
30
|
+
// @clint:begin commands
|
|
31
|
+
commands: [init, regen],
|
|
32
|
+
// @clint:end commands
|
|
33
|
+
// @clint:begin services
|
|
34
|
+
services: [],
|
|
35
|
+
// @clint:end services
|
|
36
|
+
// @clint:begin triggers
|
|
37
|
+
triggers: [specChangeTrigger],
|
|
38
|
+
// @clint:end triggers
|
|
39
|
+
// @clint:begin prompts
|
|
40
|
+
prompts: {
|
|
41
|
+
sources: [],
|
|
42
|
+
agents: {},
|
|
43
|
+
skills: {},
|
|
44
|
+
},
|
|
45
|
+
// @clint:end prompts
|
|
46
|
+
// @clint:begin events
|
|
47
|
+
events: {},
|
|
48
|
+
// @clint:end events
|
|
49
|
+
// @clint:begin interactive
|
|
50
|
+
interactive: {
|
|
51
|
+
welcome: ({ config, workdir }) => {
|
|
52
|
+
const mode = config.apiKey
|
|
53
|
+
? config.model
|
|
54
|
+
: 'demo mode — set PH_CLINT_API_KEY for real LLM responses';
|
|
55
|
+
return [
|
|
56
|
+
`ph-clint v${CLI_VERSION}`,
|
|
57
|
+
`Model: ${mode}`,
|
|
58
|
+
`Workdir: ${workdir}`,
|
|
59
|
+
'',
|
|
60
|
+
'Type a message to talk to the agent, or /help for commands.',
|
|
61
|
+
].join('\n');
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
// @clint:end interactive
|
|
65
|
+
});
|
|
66
|
+
// @clint:begin reactor
|
|
67
|
+
cli.configureReactor({
|
|
68
|
+
create: (ctx) => buildDefaultReactor(ctx, {
|
|
69
|
+
documentModels,
|
|
70
|
+
drive: { name: 'Clint' },
|
|
71
|
+
subscriptions: { documentTypes: ['powerhouse/ph-clint-project'] },
|
|
72
|
+
}),
|
|
73
|
+
switchboard: { enabled: true },
|
|
74
|
+
connect: { enabled: true, workdir: appDir },
|
|
75
|
+
});
|
|
76
|
+
// @clint:end reactor
|
|
77
|
+
// @clint:begin mastra
|
|
78
|
+
cli.configureAgent(createAgent);
|
|
79
|
+
// @clint:end mastra
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `prompts/agent-profiles/AgentBase.md` — the minimal base profile.
|
|
3
|
+
*/
|
|
4
|
+
import { getPackageName, } from '../../spec/types.js';
|
|
5
|
+
export function buildAgentBaseMd(spec) {
|
|
6
|
+
return [
|
|
7
|
+
'# Agent Base System Prompt',
|
|
8
|
+
'',
|
|
9
|
+
`You are {{agentName}}, an agent available through the ${getPackageName(spec)} CLI.`,
|
|
10
|
+
'',
|
|
11
|
+
'## Capabilities',
|
|
12
|
+
'',
|
|
13
|
+
'This base profile is a minimal placeholder. Extend it with project-specific',
|
|
14
|
+
"context, workflows, and domain knowledge. Additional sections listed in the",
|
|
15
|
+
"agent's `sections` array are concatenated after this file at build time.",
|
|
16
|
+
'',
|
|
17
|
+
].join('\n');
|
|
18
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `src/agents/agent.ts` — a minimal Mastra agent factory.
|
|
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.
|
|
7
|
+
*/
|
|
8
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
9
|
+
export declare function buildAgentTs(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
export function buildAgentTs(spec) {
|
|
2
|
+
const id = spec.name;
|
|
3
|
+
return [
|
|
4
|
+
"import type { AgentProvider, AgentSetupContext, StreamChunk } from '@powerhousedao/ph-clint';",
|
|
5
|
+
"import type { Config } from '../framework.js';",
|
|
6
|
+
'',
|
|
7
|
+
'/**',
|
|
8
|
+
' * Demo agent — deterministic echo responses. Replace with a real Mastra',
|
|
9
|
+
" * `Agent` once you've wired your model + tools.",
|
|
10
|
+
' */',
|
|
11
|
+
'function createDemoAgent(): AgentProvider {',
|
|
12
|
+
' return {',
|
|
13
|
+
` id: '${id}',`,
|
|
14
|
+
' async *stream(prompt) {',
|
|
15
|
+
' yield {',
|
|
16
|
+
" type: 'text-delta',",
|
|
17
|
+
" text: `You said: ${prompt}\\n(demo mode — set an API key and replace createDemoAgent with a Mastra Agent)`,",
|
|
18
|
+
' } satisfies StreamChunk;',
|
|
19
|
+
' },',
|
|
20
|
+
' };',
|
|
21
|
+
'}',
|
|
22
|
+
'',
|
|
23
|
+
'/**',
|
|
24
|
+
' * Agent factory invoked by `cli.configureAgent`. Receives the resolved',
|
|
25
|
+
' * config and workdir; return an AgentProvider.',
|
|
26
|
+
' */',
|
|
27
|
+
'export async function createAgent(',
|
|
28
|
+
' _ctx: AgentSetupContext<Config>,',
|
|
29
|
+
'): Promise<AgentProvider> {',
|
|
30
|
+
' return createDemoAgent();',
|
|
31
|
+
'}',
|
|
32
|
+
'',
|
|
33
|
+
].join('\n');
|
|
34
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `{name}-app/index.ts` — the top-level re-export barrel for the
|
|
3
|
+
* reactor package. Impl code imports from `'{name}-app'` instead of drilling
|
|
4
|
+
* into `'{name}-app/document-models/<slug>/v1/gen/...'`.
|
|
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).
|
|
16
|
+
*/
|
|
17
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
18
|
+
export declare function buildAppIndexTs(spec: ClintProjectSpec): string | null;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `{name}-app/index.ts` — the top-level re-export barrel for the
|
|
3
|
+
* reactor package. Impl code imports from `'{name}-app'` instead of drilling
|
|
4
|
+
* into `'{name}-app/document-models/<slug>/v1/gen/...'`.
|
|
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).
|
|
16
|
+
*/
|
|
17
|
+
import { getDocumentTypeSlug, } from '../../spec/types.js';
|
|
18
|
+
export function buildAppIndexTs(spec) {
|
|
19
|
+
if (!spec.features.powerhouse.enabled)
|
|
20
|
+
return null;
|
|
21
|
+
if (spec.documentTypes.length === 0)
|
|
22
|
+
return null;
|
|
23
|
+
const lines = [];
|
|
24
|
+
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';`);
|
|
31
|
+
}
|
|
32
|
+
return lines.join('\n') + '\n';
|
|
33
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `scripts/build-skills.ts` — the build-time skill compiler.
|
|
3
|
+
*/
|
|
4
|
+
export function buildBuildSkillsScript() {
|
|
5
|
+
return [
|
|
6
|
+
'#!/usr/bin/env tsx',
|
|
7
|
+
'/**',
|
|
8
|
+
' * Build script — compiles Handlebars templates in `prompts/` into static',
|
|
9
|
+
' * SKILL.md files and agent instruction strings under `gen/`, using',
|
|
10
|
+
" * ph-clint-dev's `buildSkills`.",
|
|
11
|
+
' */',
|
|
12
|
+
"import path from 'node:path';",
|
|
13
|
+
"import { buildSkills } from '@powerhousedao/ph-clint-dev';",
|
|
14
|
+
"import { cli } from '../src/cli.js';",
|
|
15
|
+
'',
|
|
16
|
+
'const PROJECT_ROOT = path.resolve(import.meta.dirname, \'..\');',
|
|
17
|
+
'',
|
|
18
|
+
'// @clint:begin templateVars',
|
|
19
|
+
'function loadTemplateVars(): Record<string, string> {',
|
|
20
|
+
' return {',
|
|
21
|
+
" agentName: '{{AGENT_NAME}}',",
|
|
22
|
+
' };',
|
|
23
|
+
'}',
|
|
24
|
+
'// @clint:end templateVars',
|
|
25
|
+
'',
|
|
26
|
+
'buildSkills({',
|
|
27
|
+
" include: [path.join(PROJECT_ROOT, 'prompts')],",
|
|
28
|
+
' context: loadTemplateVars(),',
|
|
29
|
+
' output: [',
|
|
30
|
+
" path.join(PROJECT_ROOT, 'gen'),",
|
|
31
|
+
" path.join(PROJECT_ROOT, 'dist', 'gen'),",
|
|
32
|
+
' ],',
|
|
33
|
+
' cli,',
|
|
34
|
+
'});',
|
|
35
|
+
'',
|
|
36
|
+
].join('\n');
|
|
37
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
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;
|
|
@@ -0,0 +1,69 @@
|
|
|
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
|
+
/** Pinned version range for peer ph-clint packages emitted into generated projects. */
|
|
9
|
+
const PH_CLINT_VERSION = '^0.1.0';
|
|
10
|
+
const POWERHOUSE_VERSION = '6.0.0-dev.170';
|
|
11
|
+
export function buildCliPackageJson(spec) {
|
|
12
|
+
const { mastra, powerhouse } = spec.features;
|
|
13
|
+
const pkgName = powerhouse.enabled
|
|
14
|
+
? `${getPackageName(spec)}-cli`
|
|
15
|
+
: getPackageName(spec);
|
|
16
|
+
const bin = getBinName(spec);
|
|
17
|
+
const dependencies = {
|
|
18
|
+
'ph-clint': PH_CLINT_VERSION,
|
|
19
|
+
zod: '^4.3.6',
|
|
20
|
+
};
|
|
21
|
+
if (mastra.enabled) {
|
|
22
|
+
dependencies['@mastra/core'] = '^1.22.0';
|
|
23
|
+
dependencies['@mastra/libsql'] = '^1.7.4';
|
|
24
|
+
dependencies['@mastra/memory'] = '^1.13.1';
|
|
25
|
+
}
|
|
26
|
+
if (powerhouse.enabled) {
|
|
27
|
+
dependencies[`${spec.name}-app`] = `file:../${spec.name}-app`;
|
|
28
|
+
dependencies['@powerhousedao/reactor'] = POWERHOUSE_VERSION;
|
|
29
|
+
dependencies['@powerhousedao/reactor-api'] = POWERHOUSE_VERSION;
|
|
30
|
+
dependencies['@powerhousedao/shared'] = POWERHOUSE_VERSION;
|
|
31
|
+
dependencies['document-model'] = POWERHOUSE_VERSION;
|
|
32
|
+
}
|
|
33
|
+
const scripts = {
|
|
34
|
+
'build:skills': 'tsx scripts/build-skills.ts',
|
|
35
|
+
build: 'pnpm build:skills && tsc',
|
|
36
|
+
dev: 'tsx src/main.ts',
|
|
37
|
+
start: 'node dist/main.js',
|
|
38
|
+
test: "NODE_OPTIONS='--experimental-vm-modules' jest --detectOpenHandles",
|
|
39
|
+
lint: 'eslint src',
|
|
40
|
+
};
|
|
41
|
+
if (mastra.enabled) {
|
|
42
|
+
scripts['mastra:dev'] = 'mastra dev';
|
|
43
|
+
scripts['mastra:build'] = 'mastra build';
|
|
44
|
+
scripts['mastra:start'] = 'mastra start';
|
|
45
|
+
}
|
|
46
|
+
scripts['publish:npm'] = 'pnpm build && pnpm publish --no-git-checks';
|
|
47
|
+
const pkg = {
|
|
48
|
+
name: pkgName,
|
|
49
|
+
version: spec.version,
|
|
50
|
+
private: true,
|
|
51
|
+
type: 'module',
|
|
52
|
+
};
|
|
53
|
+
if (spec.description)
|
|
54
|
+
pkg.description = spec.description;
|
|
55
|
+
pkg.bin = { [bin]: './dist/main.js' };
|
|
56
|
+
pkg.scripts = scripts;
|
|
57
|
+
pkg.dependencies = dependencies;
|
|
58
|
+
pkg.devDependencies = {
|
|
59
|
+
'@jest/globals': '^30.2.0',
|
|
60
|
+
'@types/node': '^25.5.2',
|
|
61
|
+
jest: '^30.2.0',
|
|
62
|
+
'ph-clint-dev': PH_CLINT_VERSION,
|
|
63
|
+
'ts-jest': '^29.4.6',
|
|
64
|
+
tsx: '^4.19.0',
|
|
65
|
+
typescript: '^6.0.2',
|
|
66
|
+
};
|
|
67
|
+
pkg.engines = { node: '>=22.13.0' };
|
|
68
|
+
return JSON.stringify(pkg, null, 2) + '\n';
|
|
69
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
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 { type ClintProjectSpec } from '../../spec/types.js';
|
|
7
|
+
export declare function buildCliTs(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
export function buildCliTs(spec) {
|
|
2
|
+
const { mastra, routine, powerhouse } = spec.features;
|
|
3
|
+
const lines = [];
|
|
4
|
+
lines.push('/**');
|
|
5
|
+
lines.push(' * CLI definition.');
|
|
6
|
+
lines.push(' *');
|
|
7
|
+
lines.push(' * Generated by ph-clint. Regions bracketed by @clint:begin/@clint:end');
|
|
8
|
+
lines.push(' * markers are rewritten by ph-clint when the project spec changes.');
|
|
9
|
+
lines.push(' * Everything outside the markers is user-editable and preserved.');
|
|
10
|
+
lines.push(' */');
|
|
11
|
+
if (powerhouse.enabled) {
|
|
12
|
+
lines.push(`import path from 'node:path';`);
|
|
13
|
+
lines.push(`import { fileURLToPath } from 'node:url';`);
|
|
14
|
+
lines.push(`import { defineCli, buildDefaultReactor } from '@powerhousedao/ph-clint';`);
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
lines.push(`import { defineCli } from '@powerhousedao/ph-clint';`);
|
|
18
|
+
}
|
|
19
|
+
lines.push(`import { CLI_NAME, CLI_VERSION } from './config.js';`);
|
|
20
|
+
lines.push(`import { configSchema, secretsSchema } from './framework.js';`);
|
|
21
|
+
lines.push('');
|
|
22
|
+
lines.push('// @clint:begin imports');
|
|
23
|
+
if (powerhouse.enabled) {
|
|
24
|
+
lines.push(`import { documentModels } from '${spec.name}-app';`);
|
|
25
|
+
}
|
|
26
|
+
if (mastra.enabled) {
|
|
27
|
+
lines.push(`import { createAgent } from './agents/agent.js';`);
|
|
28
|
+
}
|
|
29
|
+
lines.push('// @clint:end imports');
|
|
30
|
+
lines.push('');
|
|
31
|
+
if (powerhouse.enabled) {
|
|
32
|
+
lines.push(`const __dirname = path.dirname(fileURLToPath(import.meta.url));`);
|
|
33
|
+
lines.push(`const appDir = path.resolve(__dirname, '../../${spec.name}-app');`);
|
|
34
|
+
lines.push('');
|
|
35
|
+
}
|
|
36
|
+
lines.push('export const cli = defineCli({');
|
|
37
|
+
lines.push(' name: CLI_NAME,');
|
|
38
|
+
lines.push(' version: CLI_VERSION,');
|
|
39
|
+
lines.push(' description: `${CLI_NAME} v${CLI_VERSION}`,');
|
|
40
|
+
lines.push(' configSchema,');
|
|
41
|
+
lines.push(' secretsSchema,');
|
|
42
|
+
lines.push('');
|
|
43
|
+
lines.push(' // @clint:begin commands');
|
|
44
|
+
lines.push(' commands: [],');
|
|
45
|
+
lines.push(' // @clint:end commands');
|
|
46
|
+
lines.push('');
|
|
47
|
+
lines.push(' // @clint:begin services');
|
|
48
|
+
lines.push(' services: [],');
|
|
49
|
+
lines.push(' // @clint:end services');
|
|
50
|
+
lines.push('');
|
|
51
|
+
lines.push(' // @clint:begin triggers');
|
|
52
|
+
if (routine.enabled) {
|
|
53
|
+
lines.push(' triggers: [],');
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
lines.push(' triggers: [],');
|
|
57
|
+
}
|
|
58
|
+
lines.push(' // @clint:end triggers');
|
|
59
|
+
lines.push('');
|
|
60
|
+
lines.push(' // @clint:begin prompts');
|
|
61
|
+
lines.push(' prompts: {');
|
|
62
|
+
lines.push(' sources: [],');
|
|
63
|
+
lines.push(' agents: {},');
|
|
64
|
+
lines.push(' skills: {},');
|
|
65
|
+
lines.push(' },');
|
|
66
|
+
lines.push(' // @clint:end prompts');
|
|
67
|
+
lines.push('');
|
|
68
|
+
lines.push(' // @clint:begin events');
|
|
69
|
+
lines.push(' events: {},');
|
|
70
|
+
lines.push(' // @clint:end events');
|
|
71
|
+
lines.push('');
|
|
72
|
+
lines.push(' // @clint:begin interactive');
|
|
73
|
+
lines.push(' interactive: {');
|
|
74
|
+
lines.push(` welcome: ({ workdir }) =>`);
|
|
75
|
+
lines.push(' [');
|
|
76
|
+
lines.push(' `${CLI_NAME} v${CLI_VERSION}`,');
|
|
77
|
+
lines.push(' `Workdir: ${workdir}`,');
|
|
78
|
+
lines.push(" '',");
|
|
79
|
+
if (mastra.enabled) {
|
|
80
|
+
lines.push(" 'Type a message to talk to the agent, or /help for commands.',");
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
lines.push(" 'Type /help for commands.',");
|
|
84
|
+
}
|
|
85
|
+
lines.push(" ].join('\\n'),");
|
|
86
|
+
lines.push(' },');
|
|
87
|
+
lines.push(' // @clint:end interactive');
|
|
88
|
+
lines.push('});');
|
|
89
|
+
lines.push('');
|
|
90
|
+
lines.push('// @clint:begin reactor');
|
|
91
|
+
if (powerhouse.enabled) {
|
|
92
|
+
lines.push('cli.configureReactor({');
|
|
93
|
+
lines.push(' create: (ctx) =>');
|
|
94
|
+
lines.push(' buildDefaultReactor(ctx, {');
|
|
95
|
+
lines.push(' documentModels,');
|
|
96
|
+
lines.push(` drive: { name: '${spec.name}' },`);
|
|
97
|
+
lines.push(' }),');
|
|
98
|
+
lines.push(` switchboard: { enabled: ${String(powerhouse.switchboard)} },`);
|
|
99
|
+
lines.push(` connect: { enabled: ${String(powerhouse.connect)}, workdir: appDir },`);
|
|
100
|
+
lines.push('});');
|
|
101
|
+
}
|
|
102
|
+
lines.push('// @clint:end reactor');
|
|
103
|
+
lines.push('');
|
|
104
|
+
lines.push('// @clint:begin mastra');
|
|
105
|
+
if (mastra.enabled) {
|
|
106
|
+
lines.push('cli.configureAgent(createAgent);');
|
|
107
|
+
}
|
|
108
|
+
lines.push('// @clint:end mastra');
|
|
109
|
+
return lines.join('\n') + '\n';
|
|
110
|
+
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `src/config.ts` — CLI identity constants (name, version, project
|
|
3
|
+
* root path). The Zod `configSchema` / `secretsSchema` are emitted by
|
|
4
|
+
* `buildFrameworkTs` into `src/framework.ts` (user-owned, init-only) so users
|
|
5
|
+
* can extend them without fighting the generator.
|
|
6
|
+
*/
|
|
7
|
+
import { type ClintProjectSpec } from '../../spec/types.js';
|
|
8
|
+
export declare function buildConfigTs(spec: ClintProjectSpec): string;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `src/config.ts` — CLI identity constants (name, version, project
|
|
3
|
+
* root path). The Zod `configSchema` / `secretsSchema` are emitted by
|
|
4
|
+
* `buildFrameworkTs` into `src/framework.ts` (user-owned, init-only) so users
|
|
5
|
+
* can extend them without fighting the generator.
|
|
6
|
+
*/
|
|
7
|
+
import { getBinName, } from '../../spec/types.js';
|
|
8
|
+
export function buildConfigTs(spec) {
|
|
9
|
+
const cliName = getBinName(spec);
|
|
10
|
+
const lines = [];
|
|
11
|
+
lines.push(`import path from 'node:path';`);
|
|
12
|
+
lines.push(`import { fileURLToPath } from 'node:url';`);
|
|
13
|
+
lines.push('');
|
|
14
|
+
lines.push('/** CLI name — used for config resolution, env var prefixing, and .ph/ paths. */');
|
|
15
|
+
lines.push(`export const CLI_NAME = '${cliName}';`);
|
|
16
|
+
lines.push(`export const CLI_VERSION = '${spec.version}';`);
|
|
17
|
+
lines.push('');
|
|
18
|
+
lines.push('/** Project root — resolved from this file location. */');
|
|
19
|
+
lines.push('export const PROJECT_ROOT = path.resolve(path.dirname(fileURLToPath(import.meta.url)), \'..\');');
|
|
20
|
+
return lines.join('\n') + '\n';
|
|
21
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Builds `eslint.config.js` for the CLI — placeholder flat config.
|
|
3
|
+
*/
|
|
4
|
+
export function buildEslintConfigJs() {
|
|
5
|
+
return [
|
|
6
|
+
'// @clint:begin eslint',
|
|
7
|
+
'// Placeholder ESLint flat config — replaced by codegen when the',
|
|
8
|
+
"// project's lint stack is configured.",
|
|
9
|
+
'export default [];',
|
|
10
|
+
'// @clint:end eslint',
|
|
11
|
+
'',
|
|
12
|
+
].join('\n');
|
|
13
|
+
}
|