@powerhousedao/ph-clint-cli 0.0.1

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 (65) hide show
  1. package/README.md +84 -0
  2. package/dist/agents/clint-agent.d.ts +12 -0
  3. package/dist/agents/clint-agent.js +42 -0
  4. package/dist/cli.d.ts +1 -0
  5. package/dist/cli.js +122 -0
  6. package/dist/codegen/index.d.ts +11 -0
  7. package/dist/codegen/index.js +11 -0
  8. package/dist/commands/clint-project-build.d.ts +83 -0
  9. package/dist/commands/clint-project-build.js +34 -0
  10. package/dist/commands/clint-project-init.d.ts +177 -0
  11. package/dist/commands/clint-project-init.js +193 -0
  12. package/dist/commands/clint-project-publish.d.ts +92 -0
  13. package/dist/commands/clint-project-publish.js +73 -0
  14. package/dist/commands/clint-project-regen.d.ts +94 -0
  15. package/dist/commands/clint-project-regen.js +92 -0
  16. package/dist/commands/clint-skills-sync.d.ts +86 -0
  17. package/dist/commands/clint-skills-sync.js +56 -0
  18. package/dist/config.d.ts +3 -0
  19. package/dist/config.js +5 -0
  20. package/dist/framework.d.ts +501 -0
  21. package/dist/framework.gen.d.ts +77 -0
  22. package/dist/framework.gen.js +16 -0
  23. package/dist/framework.js +37 -0
  24. package/dist/gen/agent-profiles/PhClintDevAgent.md +13 -0
  25. package/dist/gen/skills/cli-setup/.cli-docs.md +135 -0
  26. package/dist/gen/skills/cli-setup/SKILL.md +125 -0
  27. package/dist/gen/skills/cli-setup/references/00.assess-cli-needs.md +53 -0
  28. package/dist/gen/skills/cli-setup/references/01.define-config-schema.md +78 -0
  29. package/dist/gen/skills/cli-setup/references/02.wire-cli.md +141 -0
  30. package/dist/gen/skills/cli-setup/references/03.add-entrypoint.md +128 -0
  31. package/dist/gen/skills/cli-setup/references/expected-outcome.md +3 -0
  32. package/dist/gen/skills/command-definition/.cli-docs.md +84 -0
  33. package/dist/gen/skills/command-definition/SKILL.md +99 -0
  34. package/dist/gen/skills/command-definition/references/00.assess-requirements.md +58 -0
  35. package/dist/gen/skills/command-definition/references/01.define-schema.md +72 -0
  36. package/dist/gen/skills/command-definition/references/02.implement-execute.md +118 -0
  37. package/dist/gen/skills/command-definition/references/03.add-prompting.md +54 -0
  38. package/dist/gen/skills/command-definition/references/expected-outcome.md +3 -0
  39. package/dist/gen/skills/service-definition/.cli-docs.md +214 -0
  40. package/dist/gen/skills/service-definition/SKILL.md +148 -0
  41. package/dist/gen/skills/service-definition/references/00.assess-service.md +69 -0
  42. package/dist/gen/skills/service-definition/references/01.define-service.md +166 -0
  43. package/dist/gen/skills/service-definition/references/02.add-preflight.md +132 -0
  44. package/dist/gen/skills/service-definition/references/03.add-project-scanner.md +82 -0
  45. package/dist/gen/skills/service-definition/references/04.wire-events.md +120 -0
  46. package/dist/gen/skills/service-definition/references/expected-outcome.md +3 -0
  47. package/dist/main.d.ts +2 -0
  48. package/dist/main.js +3 -0
  49. package/dist/mastra/index.d.ts +10 -0
  50. package/dist/mastra/index.js +11 -0
  51. package/dist/services/clint-project.d.ts +1 -0
  52. package/dist/services/clint-project.js +68 -0
  53. package/dist/spec/ensure-document.d.ts +17 -0
  54. package/dist/spec/ensure-document.js +56 -0
  55. package/dist/spec/file.d.ts +1 -0
  56. package/dist/spec/file.js +1 -0
  57. package/dist/spec/from-document.d.ts +21 -0
  58. package/dist/spec/from-document.js +18 -0
  59. package/dist/spec/types.d.ts +1 -0
  60. package/dist/spec/types.js +1 -0
  61. package/dist/triggers/publish-trigger.d.ts +81 -0
  62. package/dist/triggers/publish-trigger.js +137 -0
  63. package/dist/triggers/spec-change.d.ts +85 -0
  64. package/dist/triggers/spec-change.js +224 -0
  65. package/package.json +54 -0
@@ -0,0 +1,193 @@
1
+ /**
2
+ * `ph-clint clint-project-init` — the project bootstrap wizard.
3
+ *
4
+ * Behavior:
5
+ * 1. Resolve target dir (positional `dir`, defaults to the project name).
6
+ * 2. Assert it is empty (or `--force`).
7
+ * 3. Collect project identity + feature toggles (prompt for missing).
8
+ * 4. Assemble a ClintProjectSpec and validate with Zod.
9
+ * 5. Write the spec + emit the generated tree via `generateProject`.
10
+ * 6. (Split layout) run `ph init` in `{name}-app/`.
11
+ * 7. Run `pnpm install` in generated sub-projects unless `--skip-install`.
12
+ * 8. Print next-steps guidance.
13
+ */
14
+ import path from 'node:path';
15
+ import { defineCommand } from '../framework.js';
16
+ import { z } from 'zod';
17
+ import { clintProjectSpecSchema, } from '../spec/types.js';
18
+ import { generateProject } from '../codegen/index.js';
19
+ import { isDirEmptyEnough } from '@powerhousedao/ph-clint-dev/codegen/write';
20
+ import { runPostGenActions } from '@powerhousedao/ph-clint-dev/codegen/actions';
21
+ import { ensureSpecDocument } from '../spec/ensure-document.js';
22
+ const inputSchema = z.object({
23
+ dir: z
24
+ .string()
25
+ .optional()
26
+ .describe('Target directory (defaults to the project name)'),
27
+ name: z
28
+ .string()
29
+ .describe('Project name — bare, or `@scope/name`. Lowercase letters, digits, hyphens.'),
30
+ description: z.string().optional().describe('Short project description'),
31
+ enablePowerhouse: z
32
+ .boolean()
33
+ .default(false)
34
+ .describe('Enable Powerhouse reactor (requires split layout)'),
35
+ enableMastra: z
36
+ .boolean()
37
+ .default(false)
38
+ .describe('Enable Mastra AI agent stack'),
39
+ enableRoutine: z
40
+ .boolean()
41
+ .default(false)
42
+ .describe('Enable the tick-based routine loop'),
43
+ enableObservability: z
44
+ .boolean()
45
+ .default(false)
46
+ .describe('Wire @powerhousedao/ph-clint-observability into the generated CLI. ' +
47
+ 'The generated CLI will ask its end-user for telemetry consent on first run.'),
48
+ force: z
49
+ .boolean()
50
+ .default(false)
51
+ .describe('Overwrite files if the target directory is not empty'),
52
+ skipInstall: z
53
+ .boolean()
54
+ .default(false)
55
+ .describe('Do not run `pnpm install` after scaffolding'),
56
+ });
57
+ /** Parse `@scope/name` into { scope, name }. Auto-appends `-cli` if missing. */
58
+ function splitPackageName(raw) {
59
+ const match = /^@([a-z0-9][a-z0-9-]*)\/([a-z0-9][a-z0-9-]*)$/.exec(raw);
60
+ if (match) {
61
+ const name = match[2].endsWith('-cli') ? match[2] : `${match[2]}-cli`;
62
+ return { scope: `@${match[1]}`, name };
63
+ }
64
+ if (raw.startsWith('@')) {
65
+ throw new Error(`invalid package name "${raw}" — expected "@scope/name" with lowercase letters, digits, hyphens`);
66
+ }
67
+ if (!/^[a-z0-9][a-z0-9-]*$/.test(raw)) {
68
+ throw new Error(`invalid project name "${raw}" — expected lowercase letters, digits, hyphens`);
69
+ }
70
+ const name = raw.endsWith('-cli') ? raw : `${raw}-cli`;
71
+ return { name };
72
+ }
73
+ export function buildSpec(input) {
74
+ const { scope, name } = splitPackageName(input.name);
75
+ // Routine is forced on when Mastra is on — the REPL-only path works, but
76
+ // the agent routine loop is what most users actually want.
77
+ const routine = input.enableRoutine || input.enableMastra;
78
+ const baseName = name.replace(/-cli$/, '');
79
+ const mastra = input.enableMastra
80
+ ? {
81
+ enabled: true,
82
+ models: [{ id: 'anthropic/claude-sonnet-4-5' }],
83
+ profiles: [{ id: 'base', title: 'Base', content: 'You are a helpful assistant.' }],
84
+ mainAgent: {
85
+ id: `${baseName}-agent`,
86
+ name: `${baseName.charAt(0).toUpperCase()}${baseName.slice(1).replace(/-(\w)/g, (_, c) => ' ' + c.toUpperCase())} Agent`,
87
+ description: null,
88
+ image: null,
89
+ modelId: 'anthropic/claude-sonnet-4-5',
90
+ profileIds: ['base'],
91
+ skills: [],
92
+ toolPatterns: [],
93
+ },
94
+ subAgents: [],
95
+ }
96
+ : { enabled: false };
97
+ const candidate = {
98
+ name,
99
+ scope,
100
+ description: input.description ?? '',
101
+ features: {
102
+ powerhouse: input.enablePowerhouse ? 'Connect' : 'Disabled',
103
+ mastra,
104
+ routine: { enabled: routine },
105
+ },
106
+ };
107
+ if (input.enableObservability) {
108
+ candidate.deployment = { observabilityEnabled: true };
109
+ }
110
+ return clintProjectSpecSchema.parse(candidate);
111
+ }
112
+ export const init = defineCommand({
113
+ id: 'clint-project-init',
114
+ description: 'Initialize a new ph-clint project in the target directory',
115
+ inputSchema,
116
+ prompt: {
117
+ promptForDefaults: true,
118
+ promptOptional: ['description'],
119
+ },
120
+ execute: async (input, { workdir, stdout, reactor: getReactor, folders, runProcess }) => {
121
+ const { name: bareName } = splitPackageName(input.name);
122
+ const targetDir = path.resolve(workdir, input.dir ?? bareName);
123
+ if (!input.force) {
124
+ const empty = await isDirEmptyEnough(targetDir);
125
+ if (!empty) {
126
+ return {
127
+ text: `Error: ${targetDir} is not empty. Re-run with --force to initialize anyway,\n` +
128
+ 'or choose a different --dir.',
129
+ };
130
+ }
131
+ }
132
+ const spec = buildSpec(input);
133
+ const result = await generateProject({
134
+ targetDir,
135
+ spec,
136
+ mode: 'create',
137
+ allowNonEmpty: input.force,
138
+ });
139
+ stdout(`Generated ${result.files.length} files in ${targetDir}\n`);
140
+ // Create spec document in personal drive (if reactor available)
141
+ if (getReactor && folders) {
142
+ try {
143
+ const reactor = await getReactor();
144
+ if (reactor) {
145
+ const { docId } = await ensureSpecDocument({
146
+ spec, targetDir, reactor, folders,
147
+ });
148
+ stdout(`Created spec document ${docId} in Clint Folders/specs/${spec.name}\n`);
149
+ }
150
+ }
151
+ catch (err) {
152
+ // Non-fatal — trigger will pick it up on next startup
153
+ stdout(`Note: could not create spec document — ${err instanceof Error ? err.message : String(err)}\n`);
154
+ }
155
+ }
156
+ // Run post-generation actions (ph-init, install, build, skills-sync).
157
+ // Only skip cli-install — in split layout, ph-init handles app install
158
+ // internally, and app-build must still run so the CLI can link to it.
159
+ const skip = new Set();
160
+ if (input.skipInstall) {
161
+ skip.add('cli-install');
162
+ }
163
+ await runPostGenActions(result.pendingActions, {
164
+ log: (msg) => stdout(msg + '\n'),
165
+ runProcess,
166
+ skip,
167
+ });
168
+ const split = spec.features.powerhouse !== 'Disabled';
169
+ const next = [];
170
+ next.push('');
171
+ next.push('Next steps:');
172
+ const relDir = path.relative(workdir, targetDir) || '.';
173
+ if (split) {
174
+ next.push(` cd ${relDir}`);
175
+ if (input.skipInstall) {
176
+ next.push(' pnpm install');
177
+ }
178
+ next.push(' pnpm dev');
179
+ }
180
+ else {
181
+ next.push(` cd ${relDir}`);
182
+ if (input.skipInstall)
183
+ next.push(' pnpm install');
184
+ next.push(' pnpm dev');
185
+ }
186
+ next.push('');
187
+ next.push('Edit the project spec and run `ph-clint clint-project-regen` to regenerate.');
188
+ return {
189
+ text: next.join('\n'),
190
+ data: { targetDir, spec, fileCount: result.files.length },
191
+ };
192
+ },
193
+ });
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ export declare const clintProjectPublish: import("@powerhousedao/ph-clint").Command<z.ZodObject<{
3
+ tag: z.ZodEnum<{
4
+ dev: "dev";
5
+ staging: "staging";
6
+ production: "production";
7
+ }>;
8
+ dir: z.ZodOptional<z.ZodString>;
9
+ dryRun: z.ZodDefault<z.ZodBoolean>;
10
+ skipBuild: z.ZodDefault<z.ZodBoolean>;
11
+ skipGitCheck: z.ZodDefault<z.ZodBoolean>;
12
+ verbose: z.ZodDefault<z.ZodBoolean>;
13
+ }, z.core.$strip>, {
14
+ text: string;
15
+ data: import("@powerhousedao/ph-clint-dev/publish").PublishResult;
16
+ }, {
17
+ model: string;
18
+ devServicePort: number;
19
+ phVersion: string;
20
+ apiKey?: string | undefined;
21
+ }, import("@powerhousedao/ph-clint").InferRegistry<readonly [{
22
+ readonly version: 1;
23
+ readonly reducer: import("document-model").Reducer<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
24
+ readonly actions: {
25
+ setAgentModel: (input: import("@powerhousedao/ph-clint-app").SetAgentModelInput) => import("@powerhousedao/ph-clint-app").SetAgentModelAction;
26
+ addAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").AddAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").AddAgentProfileRefAction;
27
+ removeAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefAction;
28
+ reorderAgentProfileRefs: (input: import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsInput) => import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsAction;
29
+ addAgentSkill: (input: import("@powerhousedao/ph-clint-app").AddAgentSkillInput) => import("@powerhousedao/ph-clint-app").AddAgentSkillAction;
30
+ removeAgentSkill: (input: import("@powerhousedao/ph-clint-app").RemoveAgentSkillInput) => import("@powerhousedao/ph-clint-app").RemoveAgentSkillAction;
31
+ addAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").AddAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").AddAgentToolPatternAction;
32
+ removeAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternAction;
33
+ addSubAgent: (input: import("@powerhousedao/ph-clint-app").AddSubAgentInput) => import("@powerhousedao/ph-clint-app").AddSubAgentAction;
34
+ removeSubAgent: (input: import("@powerhousedao/ph-clint-app").RemoveSubAgentInput) => import("@powerhousedao/ph-clint-app").RemoveSubAgentAction;
35
+ setSubAgentName: (input: import("@powerhousedao/ph-clint-app").SetSubAgentNameInput) => import("@powerhousedao/ph-clint-app").SetSubAgentNameAction;
36
+ setSubAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionAction;
37
+ setMainAgentName: (input: import("@powerhousedao/ph-clint-app").SetMainAgentNameInput) => import("@powerhousedao/ph-clint-app").SetMainAgentNameAction;
38
+ setMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionAction;
39
+ clearMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionAction;
40
+ setMainAgentImage: (input: import("@powerhousedao/ph-clint-app").SetMainAgentImageInput) => import("@powerhousedao/ph-clint-app").SetMainAgentImageAction;
41
+ clearMainAgentImage: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentImageInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentImageAction;
42
+ addProfile: (input: import("@powerhousedao/ph-clint-app").AddProfileInput) => import("@powerhousedao/ph-clint-app").AddProfileAction;
43
+ updateProfile: (input: import("@powerhousedao/ph-clint-app").UpdateProfileInput) => import("@powerhousedao/ph-clint-app").UpdateProfileAction;
44
+ removeProfile: (input: import("@powerhousedao/ph-clint-app").RemoveProfileInput) => import("@powerhousedao/ph-clint-app").RemoveProfileAction;
45
+ reorderProfiles: (input: import("@powerhousedao/ph-clint-app").ReorderProfilesInput) => import("@powerhousedao/ph-clint-app").ReorderProfilesAction;
46
+ addModel: (input: import("@powerhousedao/ph-clint-app").AddModelInput) => import("@powerhousedao/ph-clint-app").AddModelAction;
47
+ removeModel: (input: import("@powerhousedao/ph-clint-app").RemoveModelInput) => import("@powerhousedao/ph-clint-app").RemoveModelAction;
48
+ enableMastra: (input: import("@powerhousedao/ph-clint-app").EnableMastraInput) => import("@powerhousedao/ph-clint-app").EnableMastraAction;
49
+ disableMastra: (input: import("@powerhousedao/ph-clint-app").DisableMastraInput) => import("@powerhousedao/ph-clint-app").DisableMastraAction;
50
+ setEnableChat: (input: import("@powerhousedao/ph-clint-app").SetEnableChatInput) => import("@powerhousedao/ph-clint-app").SetEnableChatAction;
51
+ addSupportedResource: (input: import("@powerhousedao/ph-clint-app").AddSupportedResourceInput) => import("@powerhousedao/ph-clint-app").AddSupportedResourceAction;
52
+ removeSupportedResource: (input: import("@powerhousedao/ph-clint-app").RemoveSupportedResourceInput) => import("@powerhousedao/ph-clint-app").RemoveSupportedResourceAction;
53
+ setProxyEnabled: (input: import("@powerhousedao/ph-clint-app").SetProxyEnabledInput) => import("@powerhousedao/ph-clint-app").SetProxyEnabledAction;
54
+ setObservabilityEnabled: (input: import("@powerhousedao/ph-clint-app").SetObservabilityEnabledInput) => import("@powerhousedao/ph-clint-app").SetObservabilityEnabledAction;
55
+ importSpec: (input: import("@powerhousedao/ph-clint-app").ImportSpecInput) => import("@powerhousedao/ph-clint-app").ImportSpecAction;
56
+ bumpVersion: (input: import("@powerhousedao/ph-clint-app").BumpVersionInput) => import("@powerhousedao/ph-clint-app").BumpVersionAction;
57
+ publishDev: (input: import("@powerhousedao/ph-clint-app").PublishDevInput) => import("@powerhousedao/ph-clint-app").PublishDevAction;
58
+ publishStaging: (input: import("@powerhousedao/ph-clint-app").PublishStagingInput) => import("@powerhousedao/ph-clint-app").PublishStagingAction;
59
+ publishProduction: (input: import("@powerhousedao/ph-clint-app").PublishProductionInput) => import("@powerhousedao/ph-clint-app").PublishProductionAction;
60
+ setPublishStatus: (input: import("@powerhousedao/ph-clint-app").SetPublishStatusInput) => import("@powerhousedao/ph-clint-app").SetPublishStatusAction;
61
+ addExternalSkill: (input: import("@powerhousedao/ph-clint-app").AddExternalSkillInput) => import("@powerhousedao/ph-clint-app").AddExternalSkillAction;
62
+ removeExternalSkill: (input: import("@powerhousedao/ph-clint-app").RemoveExternalSkillInput) => import("@powerhousedao/ph-clint-app").RemoveExternalSkillAction;
63
+ setExternalSkillName: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillNameInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillNameAction;
64
+ setExternalSkillGithubUrl: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlAction;
65
+ addPowerhousePackage: (input: import("@powerhousedao/ph-clint-app").AddPowerhousePackageInput) => import("@powerhousedao/ph-clint-app").AddPowerhousePackageAction;
66
+ removePowerhousePackage: (input: import("@powerhousedao/ph-clint-app").RemovePowerhousePackageInput) => import("@powerhousedao/ph-clint-app").RemovePowerhousePackageAction;
67
+ addPackageDocumentType: (input: import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeAction;
68
+ removePackageDocumentType: (input: import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeAction;
69
+ setPackageVersion: (input: import("@powerhousedao/ph-clint-app").SetPackageVersionInput) => import("@powerhousedao/ph-clint-app").SetPackageVersionAction;
70
+ enableRoutine: (input: import("@powerhousedao/ph-clint-app").EnableRoutineInput) => import("@powerhousedao/ph-clint-app").EnableRoutineAction;
71
+ disableRoutine: (input: import("@powerhousedao/ph-clint-app").DisableRoutineInput) => import("@powerhousedao/ph-clint-app").DisableRoutineAction;
72
+ setPowerhouseLevel: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseLevelInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseLevelAction;
73
+ setDescription: (input: import("@powerhousedao/ph-clint-app").SetDescriptionInput) => import("@powerhousedao/ph-clint-app").SetDescriptionAction;
74
+ setVersion: (input: import("@powerhousedao/ph-clint-app").SetVersionInput) => import("@powerhousedao/ph-clint-app").SetVersionAction;
75
+ setPackageIdentifier: (input: import("@powerhousedao/ph-clint-app").SetPackageIdentifierInput) => import("@powerhousedao/ph-clint-app").SetPackageIdentifierAction;
76
+ setName: (name: string | {
77
+ name: string;
78
+ }) => import("document-model").SetNameAction;
79
+ setPreferredEditor: (input: string | null | {
80
+ preferredEditor: string | null;
81
+ }) => import("document-model").SetPreferredEditorAction;
82
+ undo: (count?: number, scope?: string) => import("document-model").UndoAction;
83
+ redo: (count?: number, scope?: string) => import("document-model").RedoAction;
84
+ prune: (start?: number, end?: number, scope?: string) => import("document-model").SchemaPruneAction;
85
+ loadState: <TState extends import("document-model").PHBaseState = import("document-model").PHBaseState>(state: TState & {
86
+ name: string;
87
+ }, operations: number) => import("document-model").LoadStateAction;
88
+ noop: (scope?: string) => import("document-model").NOOPAction;
89
+ };
90
+ readonly utils: import("document-model").DocumentModelUtils<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
91
+ readonly documentModel: import("document-model").DocumentModelPHState;
92
+ }]>>;
@@ -0,0 +1,73 @@
1
+ import path from 'node:path';
2
+ import { defineCommand } from '../framework.js';
3
+ import { z } from 'zod';
4
+ import { resolvePublishPlan, buildPackages, publishPackages, } from '@powerhousedao/ph-clint-dev/publish';
5
+ const inputSchema = z.object({
6
+ tag: z.enum(['dev', 'staging', 'production']).describe('Release channel'),
7
+ dir: z.string().optional().describe('Project root directory'),
8
+ dryRun: z.boolean().default(false).describe('Preview without publishing'),
9
+ skipBuild: z.boolean().default(false),
10
+ skipGitCheck: z.boolean().default(false).describe('Skip git working tree check'),
11
+ verbose: z.boolean().default(false),
12
+ });
13
+ function formatPlanPreview(plan) {
14
+ const lines = [];
15
+ const distTag = plan.tag === 'production' ? 'latest' : plan.tag;
16
+ lines.push(`Publish plan:`);
17
+ lines.push(` Group: ${plan.groupName}`);
18
+ lines.push(` Version: ${plan.version}`);
19
+ lines.push(` Tag: ${distTag}`);
20
+ lines.push(` Registry: ${plan.registry}`);
21
+ lines.push(` Packages:`);
22
+ for (const pkg of plan.packages) {
23
+ lines.push(` - ${pkg.name}`);
24
+ }
25
+ return lines.join('\n');
26
+ }
27
+ export const clintProjectPublish = defineCommand({
28
+ id: 'clint-project-publish',
29
+ description: 'Publish project packages to npm',
30
+ inputSchema,
31
+ execute: async (input, { workdir, stdout }) => {
32
+ const dir = path.resolve(input.dir ?? workdir);
33
+ const logLines = [];
34
+ const log = (msg) => {
35
+ logLines.push(msg);
36
+ stdout(msg + '\n');
37
+ };
38
+ // 1. Resolve plan — discover config from the target dir, not process.cwd().
39
+ const configFile = path.join(dir, 'publish.config.js');
40
+ const plan = await resolvePublishPlan({
41
+ tag: input.tag,
42
+ configPath: configFile,
43
+ skipGitCheck: input.dryRun || input.skipGitCheck,
44
+ log,
45
+ });
46
+ // 2. Show preview
47
+ stdout(formatPlanPreview(plan) + '\n');
48
+ // 3. Build
49
+ if (!input.skipBuild) {
50
+ await buildPackages(plan, { verbose: input.verbose, log });
51
+ }
52
+ // 4. Publish (or dry-run)
53
+ const result = await publishPackages(plan, {
54
+ dryRun: input.dryRun,
55
+ verbose: input.verbose,
56
+ log,
57
+ });
58
+ if (result.success) {
59
+ return {
60
+ text: result.dryRun
61
+ ? `Dry run complete — ${plan.packages.length} packages validated at ${result.version}.`
62
+ : `Published ${result.published.length} packages at ${result.version}.`,
63
+ data: result,
64
+ };
65
+ }
66
+ else {
67
+ return {
68
+ text: `Publish failed. Published: ${result.published.length}, Failed: ${result.failed.length}.`,
69
+ data: result,
70
+ };
71
+ }
72
+ },
73
+ });
@@ -0,0 +1,94 @@
1
+ import { z } from 'zod';
2
+ export declare const regen: import("@powerhousedao/ph-clint").Command<z.ZodObject<{
3
+ dir: z.ZodOptional<z.ZodString>;
4
+ force: z.ZodDefault<z.ZodBoolean>;
5
+ }, z.core.$strip>, {
6
+ text: string;
7
+ data?: undefined;
8
+ } | {
9
+ text: string;
10
+ data: {
11
+ mode: "create" | "update";
12
+ files: string[];
13
+ skipped: string[];
14
+ deleted: string[];
15
+ migrated: boolean;
16
+ warnings: string[];
17
+ };
18
+ }, {
19
+ model: string;
20
+ devServicePort: number;
21
+ phVersion: string;
22
+ apiKey?: string | undefined;
23
+ }, import("@powerhousedao/ph-clint").InferRegistry<readonly [{
24
+ readonly version: 1;
25
+ readonly reducer: import("document-model").Reducer<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
26
+ readonly actions: {
27
+ setAgentModel: (input: import("@powerhousedao/ph-clint-app").SetAgentModelInput) => import("@powerhousedao/ph-clint-app").SetAgentModelAction;
28
+ addAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").AddAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").AddAgentProfileRefAction;
29
+ removeAgentProfileRef: (input: import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefInput) => import("@powerhousedao/ph-clint-app").RemoveAgentProfileRefAction;
30
+ reorderAgentProfileRefs: (input: import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsInput) => import("@powerhousedao/ph-clint-app").ReorderAgentProfileRefsAction;
31
+ addAgentSkill: (input: import("@powerhousedao/ph-clint-app").AddAgentSkillInput) => import("@powerhousedao/ph-clint-app").AddAgentSkillAction;
32
+ removeAgentSkill: (input: import("@powerhousedao/ph-clint-app").RemoveAgentSkillInput) => import("@powerhousedao/ph-clint-app").RemoveAgentSkillAction;
33
+ addAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").AddAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").AddAgentToolPatternAction;
34
+ removeAgentToolPattern: (input: import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternInput) => import("@powerhousedao/ph-clint-app").RemoveAgentToolPatternAction;
35
+ addSubAgent: (input: import("@powerhousedao/ph-clint-app").AddSubAgentInput) => import("@powerhousedao/ph-clint-app").AddSubAgentAction;
36
+ removeSubAgent: (input: import("@powerhousedao/ph-clint-app").RemoveSubAgentInput) => import("@powerhousedao/ph-clint-app").RemoveSubAgentAction;
37
+ setSubAgentName: (input: import("@powerhousedao/ph-clint-app").SetSubAgentNameInput) => import("@powerhousedao/ph-clint-app").SetSubAgentNameAction;
38
+ setSubAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetSubAgentDescriptionAction;
39
+ setMainAgentName: (input: import("@powerhousedao/ph-clint-app").SetMainAgentNameInput) => import("@powerhousedao/ph-clint-app").SetMainAgentNameAction;
40
+ setMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").SetMainAgentDescriptionAction;
41
+ clearMainAgentDescription: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentDescriptionAction;
42
+ setMainAgentImage: (input: import("@powerhousedao/ph-clint-app").SetMainAgentImageInput) => import("@powerhousedao/ph-clint-app").SetMainAgentImageAction;
43
+ clearMainAgentImage: (input: import("@powerhousedao/ph-clint-app").ClearMainAgentImageInput) => import("@powerhousedao/ph-clint-app").ClearMainAgentImageAction;
44
+ addProfile: (input: import("@powerhousedao/ph-clint-app").AddProfileInput) => import("@powerhousedao/ph-clint-app").AddProfileAction;
45
+ updateProfile: (input: import("@powerhousedao/ph-clint-app").UpdateProfileInput) => import("@powerhousedao/ph-clint-app").UpdateProfileAction;
46
+ removeProfile: (input: import("@powerhousedao/ph-clint-app").RemoveProfileInput) => import("@powerhousedao/ph-clint-app").RemoveProfileAction;
47
+ reorderProfiles: (input: import("@powerhousedao/ph-clint-app").ReorderProfilesInput) => import("@powerhousedao/ph-clint-app").ReorderProfilesAction;
48
+ addModel: (input: import("@powerhousedao/ph-clint-app").AddModelInput) => import("@powerhousedao/ph-clint-app").AddModelAction;
49
+ removeModel: (input: import("@powerhousedao/ph-clint-app").RemoveModelInput) => import("@powerhousedao/ph-clint-app").RemoveModelAction;
50
+ enableMastra: (input: import("@powerhousedao/ph-clint-app").EnableMastraInput) => import("@powerhousedao/ph-clint-app").EnableMastraAction;
51
+ disableMastra: (input: import("@powerhousedao/ph-clint-app").DisableMastraInput) => import("@powerhousedao/ph-clint-app").DisableMastraAction;
52
+ setEnableChat: (input: import("@powerhousedao/ph-clint-app").SetEnableChatInput) => import("@powerhousedao/ph-clint-app").SetEnableChatAction;
53
+ addSupportedResource: (input: import("@powerhousedao/ph-clint-app").AddSupportedResourceInput) => import("@powerhousedao/ph-clint-app").AddSupportedResourceAction;
54
+ removeSupportedResource: (input: import("@powerhousedao/ph-clint-app").RemoveSupportedResourceInput) => import("@powerhousedao/ph-clint-app").RemoveSupportedResourceAction;
55
+ setProxyEnabled: (input: import("@powerhousedao/ph-clint-app").SetProxyEnabledInput) => import("@powerhousedao/ph-clint-app").SetProxyEnabledAction;
56
+ setObservabilityEnabled: (input: import("@powerhousedao/ph-clint-app").SetObservabilityEnabledInput) => import("@powerhousedao/ph-clint-app").SetObservabilityEnabledAction;
57
+ importSpec: (input: import("@powerhousedao/ph-clint-app").ImportSpecInput) => import("@powerhousedao/ph-clint-app").ImportSpecAction;
58
+ bumpVersion: (input: import("@powerhousedao/ph-clint-app").BumpVersionInput) => import("@powerhousedao/ph-clint-app").BumpVersionAction;
59
+ publishDev: (input: import("@powerhousedao/ph-clint-app").PublishDevInput) => import("@powerhousedao/ph-clint-app").PublishDevAction;
60
+ publishStaging: (input: import("@powerhousedao/ph-clint-app").PublishStagingInput) => import("@powerhousedao/ph-clint-app").PublishStagingAction;
61
+ publishProduction: (input: import("@powerhousedao/ph-clint-app").PublishProductionInput) => import("@powerhousedao/ph-clint-app").PublishProductionAction;
62
+ setPublishStatus: (input: import("@powerhousedao/ph-clint-app").SetPublishStatusInput) => import("@powerhousedao/ph-clint-app").SetPublishStatusAction;
63
+ addExternalSkill: (input: import("@powerhousedao/ph-clint-app").AddExternalSkillInput) => import("@powerhousedao/ph-clint-app").AddExternalSkillAction;
64
+ removeExternalSkill: (input: import("@powerhousedao/ph-clint-app").RemoveExternalSkillInput) => import("@powerhousedao/ph-clint-app").RemoveExternalSkillAction;
65
+ setExternalSkillName: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillNameInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillNameAction;
66
+ setExternalSkillGithubUrl: (input: import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlInput) => import("@powerhousedao/ph-clint-app").SetExternalSkillGithubUrlAction;
67
+ addPowerhousePackage: (input: import("@powerhousedao/ph-clint-app").AddPowerhousePackageInput) => import("@powerhousedao/ph-clint-app").AddPowerhousePackageAction;
68
+ removePowerhousePackage: (input: import("@powerhousedao/ph-clint-app").RemovePowerhousePackageInput) => import("@powerhousedao/ph-clint-app").RemovePowerhousePackageAction;
69
+ addPackageDocumentType: (input: import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").AddPackageDocumentTypeAction;
70
+ removePackageDocumentType: (input: import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeInput) => import("@powerhousedao/ph-clint-app").RemovePackageDocumentTypeAction;
71
+ setPackageVersion: (input: import("@powerhousedao/ph-clint-app").SetPackageVersionInput) => import("@powerhousedao/ph-clint-app").SetPackageVersionAction;
72
+ enableRoutine: (input: import("@powerhousedao/ph-clint-app").EnableRoutineInput) => import("@powerhousedao/ph-clint-app").EnableRoutineAction;
73
+ disableRoutine: (input: import("@powerhousedao/ph-clint-app").DisableRoutineInput) => import("@powerhousedao/ph-clint-app").DisableRoutineAction;
74
+ setPowerhouseLevel: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseLevelInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseLevelAction;
75
+ setDescription: (input: import("@powerhousedao/ph-clint-app").SetDescriptionInput) => import("@powerhousedao/ph-clint-app").SetDescriptionAction;
76
+ setVersion: (input: import("@powerhousedao/ph-clint-app").SetVersionInput) => import("@powerhousedao/ph-clint-app").SetVersionAction;
77
+ setPackageIdentifier: (input: import("@powerhousedao/ph-clint-app").SetPackageIdentifierInput) => import("@powerhousedao/ph-clint-app").SetPackageIdentifierAction;
78
+ setName: (name: string | {
79
+ name: string;
80
+ }) => import("document-model").SetNameAction;
81
+ setPreferredEditor: (input: string | null | {
82
+ preferredEditor: string | null;
83
+ }) => import("document-model").SetPreferredEditorAction;
84
+ undo: (count?: number, scope?: string) => import("document-model").UndoAction;
85
+ redo: (count?: number, scope?: string) => import("document-model").RedoAction;
86
+ prune: (start?: number, end?: number, scope?: string) => import("document-model").SchemaPruneAction;
87
+ loadState: <TState extends import("document-model").PHBaseState = import("document-model").PHBaseState>(state: TState & {
88
+ name: string;
89
+ }, operations: number) => import("document-model").LoadStateAction;
90
+ noop: (scope?: string) => import("document-model").NOOPAction;
91
+ };
92
+ readonly utils: import("document-model").DocumentModelUtils<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
93
+ readonly documentModel: import("document-model").DocumentModelPHState;
94
+ }]>>;
@@ -0,0 +1,92 @@
1
+ /**
2
+ * `ph-clint clint-project-regen` — reconcile an existing project against its persisted
3
+ * spec. Equivalent to running the generator in update mode.
4
+ *
5
+ * Run inside a project directory (or pass `--dir`). If the spec has flipped
6
+ * `features.powerhouse.enabled` since the last run, the flat → split
7
+ * migration fires first.
8
+ */
9
+ import path from 'node:path';
10
+ import { defineCommand } from '../framework.js';
11
+ import { z } from 'zod';
12
+ import { readProjectSpec } from '../spec/file.js';
13
+ import { generateProject } from '../codegen/index.js';
14
+ import { runPostGenActions } from '@powerhousedao/ph-clint-dev/codegen/actions';
15
+ import { ensureSpecDocument } from '../spec/ensure-document.js';
16
+ const inputSchema = z.object({
17
+ dir: z
18
+ .string()
19
+ .optional()
20
+ .describe('Project directory (defaults to the current directory)'),
21
+ force: z
22
+ .boolean()
23
+ .default(false)
24
+ .describe('Overwrite user-edited managed files and bypass the git-dirty guard'),
25
+ });
26
+ export const regen = defineCommand({
27
+ id: 'clint-project-regen',
28
+ description: 'Regenerate project files from the persisted spec',
29
+ inputSchema,
30
+ execute: async (input, { workdir, stdout, log, runProcess, reactor: getReactor, folders }) => {
31
+ const targetDir = path.resolve(workdir, input.dir ?? '.');
32
+ const spec = await readProjectSpec(targetDir);
33
+ if (!spec) {
34
+ return {
35
+ text: `Error: no spec found at ${targetDir}/.ph/ph-clint-cli/project-spec.json.\n` +
36
+ 'Run `ph-clint clint-project-init` first to scaffold a new project.',
37
+ };
38
+ }
39
+ const warnings = [];
40
+ const result = await generateProject({
41
+ targetDir,
42
+ spec,
43
+ mode: 'update',
44
+ force: input.force,
45
+ onWarn: (m) => warnings.push(m),
46
+ });
47
+ const lines = [];
48
+ if (result.migrated)
49
+ lines.push('Migrated layout: flat → split.');
50
+ lines.push(`Wrote ${result.files.length} file(s); skipped ${result.skipped.length}; deleted ${result.deleted.length}.`);
51
+ for (const w of warnings) {
52
+ if (log)
53
+ log.warn(w);
54
+ else
55
+ stdout('warning: ' + w + '\n');
56
+ }
57
+ // Ensure spec document exists in drive (recover if deleted)
58
+ if (getReactor && folders) {
59
+ try {
60
+ const reactor = await getReactor();
61
+ if (reactor) {
62
+ const { docId, created } = await ensureSpecDocument({
63
+ spec, targetDir, reactor, folders,
64
+ });
65
+ if (created) {
66
+ lines.push(`Created spec document ${docId} in Clint Folders/specs/${spec.name}`);
67
+ }
68
+ }
69
+ }
70
+ catch (err) {
71
+ log?.warn(`Could not ensure spec document: ${err instanceof Error ? err.message : String(err)}`);
72
+ }
73
+ }
74
+ stdout(lines.join('\n') + '\n');
75
+ // Run post-generation actions (install, build, skills-sync).
76
+ await runPostGenActions(result.pendingActions, {
77
+ log: (msg) => stdout(msg + '\n'),
78
+ runProcess,
79
+ });
80
+ return {
81
+ text: lines.join('\n'),
82
+ data: {
83
+ mode: result.mode,
84
+ files: result.files.map((f) => f.relativePath),
85
+ skipped: result.skipped.map((f) => f.relativePath),
86
+ deleted: result.deleted.map((f) => f.relativePath),
87
+ migrated: result.migrated,
88
+ warnings,
89
+ },
90
+ };
91
+ },
92
+ });