@powerhousedao/ph-clint-cli 0.1.0-dev.5 → 0.1.0-dev.50
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cli.js +50 -9
- package/dist/codegen/actions.d.ts +46 -0
- package/dist/codegen/actions.js +442 -0
- package/dist/codegen/builders/agent-ts.d.ts +4 -4
- package/dist/codegen/builders/agent-ts.js +92 -2
- package/dist/codegen/builders/app-index-ts.d.ts +3 -10
- package/dist/codegen/builders/app-index-ts.js +10 -14
- package/dist/codegen/builders/cli-package-json.js +46 -14
- package/dist/codegen/builders/cli-ts.js +87 -25
- package/dist/codegen/builders/config-ts.d.ts +1 -1
- package/dist/codegen/builders/config-ts.js +2 -8
- package/dist/codegen/builders/demo-agent-ts.d.ts +8 -0
- package/dist/codegen/builders/demo-agent-ts.js +50 -0
- package/dist/codegen/builders/eslint-config-js.d.ts +1 -1
- package/dist/codegen/builders/eslint-config-js.js +7 -4
- package/dist/codegen/builders/framework-gen-ts.d.ts +4 -5
- package/dist/codegen/builders/framework-gen-ts.js +26 -18
- package/dist/codegen/builders/framework-ts.js +33 -7
- package/dist/codegen/builders/index.d.ts +10 -1
- package/dist/codegen/builders/index.js +30 -5
- package/dist/codegen/builders/manifest-json.d.ts +6 -0
- package/dist/codegen/builders/manifest-json.js +31 -0
- package/dist/codegen/builders/mastra-index-ts.d.ts +3 -0
- package/dist/codegen/builders/mastra-index-ts.js +47 -5
- package/dist/codegen/builders/publish-config-js.d.ts +8 -0
- package/dist/codegen/builders/publish-config-js.js +33 -0
- package/dist/codegen/builders/publish-config-ts.d.ts +8 -0
- package/dist/codegen/builders/publish-config-ts.js +32 -0
- package/dist/codegen/builders/readme-md.js +7 -6
- package/dist/codegen/builders/root-package-json.d.ts +3 -0
- package/dist/codegen/builders/root-package-json.js +26 -14
- package/dist/codegen/builders/smoke-test-ts.d.ts +2 -0
- package/dist/codegen/builders/smoke-test-ts.js +15 -0
- package/dist/codegen/generated.d.ts +17 -0
- package/dist/codegen/generated.js +49 -0
- package/dist/codegen/index.d.ts +3 -0
- package/dist/codegen/index.js +154 -23
- package/dist/codegen/scaffold.d.ts +41 -3
- package/dist/codegen/scaffold.js +141 -16
- package/dist/commands/clint-project-build.js +10 -27
- package/dist/commands/clint-project-init.d.ts +34 -9
- package/dist/commands/clint-project-init.js +46 -42
- package/dist/commands/clint-project-publish.d.ts +1 -0
- package/dist/commands/clint-project-publish.js +5 -3
- package/dist/commands/clint-project-regen.js +25 -1
- package/dist/commands/clint-skills-sync.d.ts +10 -0
- package/dist/commands/clint-skills-sync.js +56 -0
- package/dist/framework.d.ts +5 -169
- package/dist/framework.gen.d.ts +1 -32
- package/dist/framework.js +0 -4
- package/{prompts/agent-profiles/AgentBase.md → dist/gen/agent-profiles/PhClintDevAgent.md} +1 -1
- package/dist/gen/skills/cli-setup/.cli-docs.md +135 -0
- package/dist/gen/skills/cli-setup/SKILL.md +125 -0
- package/dist/gen/skills/cli-setup/references/00.assess-cli-needs.md +53 -0
- package/dist/gen/skills/cli-setup/references/01.define-config-schema.md +78 -0
- package/dist/gen/skills/cli-setup/references/02.wire-cli.md +141 -0
- package/dist/gen/skills/cli-setup/references/03.add-entrypoint.md +128 -0
- package/dist/gen/skills/cli-setup/references/expected-outcome.md +3 -0
- package/dist/gen/skills/command-definition/.cli-docs.md +84 -0
- package/dist/gen/skills/command-definition/SKILL.md +99 -0
- package/dist/gen/skills/command-definition/references/00.assess-requirements.md +58 -0
- package/dist/gen/skills/command-definition/references/01.define-schema.md +72 -0
- package/dist/gen/skills/command-definition/references/02.implement-execute.md +118 -0
- package/dist/gen/skills/command-definition/references/03.add-prompting.md +54 -0
- package/dist/gen/skills/command-definition/references/expected-outcome.md +3 -0
- package/dist/gen/skills/service-definition/.cli-docs.md +214 -0
- package/dist/gen/skills/service-definition/SKILL.md +148 -0
- package/dist/gen/skills/service-definition/references/00.assess-service.md +69 -0
- package/dist/gen/skills/service-definition/references/01.define-service.md +166 -0
- package/dist/gen/skills/service-definition/references/02.add-preflight.md +132 -0
- package/dist/gen/skills/service-definition/references/03.add-project-scanner.md +82 -0
- package/dist/gen/skills/service-definition/references/04.wire-events.md +120 -0
- package/dist/gen/skills/service-definition/references/expected-outcome.md +3 -0
- package/dist/services/clint-project.js +21 -0
- package/dist/skills/sync.d.ts +40 -0
- package/dist/skills/sync.js +119 -0
- package/dist/spec/ensure-document.d.ts +17 -0
- package/dist/spec/ensure-document.js +62 -0
- package/dist/spec/from-document.d.ts +4 -1
- package/dist/spec/from-document.js +4 -16
- package/dist/spec/types.d.ts +92 -9
- package/dist/spec/types.js +104 -32
- package/dist/triggers/publish-trigger.d.ts +10 -0
- package/dist/triggers/publish-trigger.js +169 -0
- package/dist/triggers/spec-change.d.ts +5 -34
- package/dist/triggers/spec-change.js +129 -102
- package/package.json +7 -7
- package/prompts/skills-ext/.gitkeep +0 -0
- package/prompts/skills-tpl/.gitkeep +0 -0
package/dist/spec/types.d.ts
CHANGED
|
@@ -9,32 +9,102 @@
|
|
|
9
9
|
* generator step actually needs it.
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
+
/**
|
|
13
|
+
* Ordered Powerhouse integration level. Higher levels imply all lower ones:
|
|
14
|
+
* Disabled → Reactor → Switchboard → Connect
|
|
15
|
+
*/
|
|
16
|
+
export declare const POWERHOUSE_LEVELS: readonly ["Disabled", "Reactor", "Switchboard", "Connect"];
|
|
17
|
+
export declare const powerhouseLevelSchema: z.ZodDefault<z.ZodEnum<{
|
|
18
|
+
Disabled: "Disabled";
|
|
19
|
+
Reactor: "Reactor";
|
|
20
|
+
Switchboard: "Switchboard";
|
|
21
|
+
Connect: "Connect";
|
|
22
|
+
}>>;
|
|
23
|
+
export type PowerhouseLevel = z.infer<typeof powerhouseLevelSchema>;
|
|
24
|
+
/** Check whether `level` is at least `threshold` in the ordered enum. */
|
|
25
|
+
export declare function phAtLeast(level: PowerhouseLevel, threshold: PowerhouseLevel): boolean;
|
|
26
|
+
export declare const agentModelSchema: z.ZodObject<{
|
|
27
|
+
id: z.ZodString;
|
|
28
|
+
isDefault: z.ZodBoolean;
|
|
29
|
+
}, z.core.$strip>;
|
|
30
|
+
export type AgentModel = z.infer<typeof agentModelSchema>;
|
|
31
|
+
export declare const agentProfileSchema: z.ZodObject<{
|
|
32
|
+
id: z.ZodString;
|
|
33
|
+
title: z.ZodString;
|
|
34
|
+
content: z.ZodString;
|
|
35
|
+
}, z.core.$strip>;
|
|
36
|
+
export type AgentProfile = z.infer<typeof agentProfileSchema>;
|
|
37
|
+
export declare const powerhousePackageSchema: z.ZodObject<{
|
|
38
|
+
id: z.ZodString;
|
|
39
|
+
packageName: z.ZodString;
|
|
40
|
+
documentTypes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
41
|
+
version: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
42
|
+
}, z.core.$strip>;
|
|
43
|
+
export type PowerhousePackage = z.infer<typeof powerhousePackageSchema>;
|
|
44
|
+
export declare const externalSkillSchema: z.ZodObject<{
|
|
45
|
+
id: z.ZodString;
|
|
46
|
+
name: z.ZodString;
|
|
47
|
+
githubUrl: z.ZodString;
|
|
48
|
+
}, z.core.$strip>;
|
|
49
|
+
export type ExternalSkill = z.infer<typeof externalSkillSchema>;
|
|
12
50
|
export declare const clintProjectSpecSchema: z.ZodObject<{
|
|
13
51
|
name: z.ZodString;
|
|
14
52
|
scope: z.ZodOptional<z.ZodString>;
|
|
15
53
|
version: z.ZodDefault<z.ZodString>;
|
|
16
54
|
description: z.ZodDefault<z.ZodString>;
|
|
17
|
-
bin: z.ZodOptional<z.ZodString>;
|
|
18
55
|
features: z.ZodDefault<z.ZodObject<{
|
|
19
|
-
powerhouse: z.ZodDefault<z.
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
56
|
+
powerhouse: z.ZodDefault<z.ZodEnum<{
|
|
57
|
+
Disabled: "Disabled";
|
|
58
|
+
Reactor: "Reactor";
|
|
59
|
+
Switchboard: "Switchboard";
|
|
60
|
+
Connect: "Connect";
|
|
61
|
+
}>>;
|
|
24
62
|
mastra: z.ZodDefault<z.ZodObject<{
|
|
25
63
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
64
|
+
agentId: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
65
|
+
agentName: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
66
|
+
agentDescription: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
67
|
+
agentImage: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
68
|
+
models: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
69
|
+
id: z.ZodString;
|
|
70
|
+
isDefault: z.ZodBoolean;
|
|
71
|
+
}, z.core.$strip>>>;
|
|
72
|
+
profiles: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
73
|
+
id: z.ZodString;
|
|
74
|
+
title: z.ZodString;
|
|
75
|
+
content: z.ZodString;
|
|
76
|
+
}, z.core.$strip>>>;
|
|
77
|
+
common: z.ZodDefault<z.ZodObject<{
|
|
78
|
+
enableChat: z.ZodDefault<z.ZodBoolean>;
|
|
79
|
+
}, z.core.$strip>>;
|
|
26
80
|
}, z.core.$strip>>;
|
|
27
81
|
routine: z.ZodDefault<z.ZodObject<{
|
|
28
82
|
enabled: z.ZodDefault<z.ZodBoolean>;
|
|
29
83
|
}, z.core.$strip>>;
|
|
30
84
|
}, z.core.$strip>>;
|
|
31
|
-
|
|
85
|
+
packages: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
86
|
+
id: z.ZodString;
|
|
87
|
+
packageName: z.ZodString;
|
|
88
|
+
documentTypes: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
89
|
+
version: z.ZodDefault<z.ZodNullable<z.ZodString>>;
|
|
90
|
+
}, z.core.$strip>>>;
|
|
91
|
+
externalSkills: z.ZodDefault<z.ZodArray<z.ZodObject<{
|
|
92
|
+
id: z.ZodString;
|
|
93
|
+
name: z.ZodString;
|
|
94
|
+
githubUrl: z.ZodString;
|
|
95
|
+
}, z.core.$strip>>>;
|
|
96
|
+
deployment: z.ZodDefault<z.ZodObject<{
|
|
97
|
+
proxyEnabled: z.ZodDefault<z.ZodBoolean>;
|
|
98
|
+
supportedResources: z.ZodDefault<z.ZodArray<z.ZodString>>;
|
|
99
|
+
}, z.core.$strip>>;
|
|
100
|
+
documentId: z.ZodOptional<z.ZodString>;
|
|
101
|
+
documentType: z.ZodOptional<z.ZodString>;
|
|
32
102
|
}, z.core.$strip>;
|
|
33
103
|
export type ClintProjectSpec = z.infer<typeof clintProjectSpecSchema>;
|
|
34
104
|
export type ClintProjectSpecInput = z.input<typeof clintProjectSpecSchema>;
|
|
35
|
-
/** npm package name (e.g. `@scope/
|
|
105
|
+
/** npm package name (e.g. `@scope/my-tool-cli` or `my-tool-cli`). */
|
|
36
106
|
export declare function getPackageName(spec: ClintProjectSpec): string;
|
|
37
|
-
/** bin name (
|
|
107
|
+
/** bin name (strips -cli suffix, e.g. `my-tool-cli` → `my-tool`). */
|
|
38
108
|
export declare function getBinName(spec: ClintProjectSpec): string;
|
|
39
109
|
/**
|
|
40
110
|
* Name of the CLI sub-folder when the project is split (Powerhouse enabled).
|
|
@@ -45,6 +115,19 @@ export declare function getCliFolderName(spec: ClintProjectSpec): string;
|
|
|
45
115
|
* Name of the reactor-package sub-folder when the project is split.
|
|
46
116
|
*/
|
|
47
117
|
export declare function getAppFolderName(spec: ClintProjectSpec): string;
|
|
118
|
+
/**
|
|
119
|
+
* Flat list of all document types across all packages. Convenience for
|
|
120
|
+
* codegen that needs to iterate every registered document type regardless
|
|
121
|
+
* of which package provides it.
|
|
122
|
+
*/
|
|
123
|
+
export declare function getAllDocumentTypes(spec: ClintProjectSpec): string[];
|
|
124
|
+
/**
|
|
125
|
+
* The app npm package name (`@scope/my-tool-app` or `my-tool-app`).
|
|
126
|
+
* Matches what the document model reducer stores in `packages[].packageName`.
|
|
127
|
+
*/
|
|
128
|
+
export declare function getAppPackageName(spec: ClintProjectSpec): string;
|
|
129
|
+
/** Directory name for the app package (e.g. `my-tool-app`, no scope prefix). */
|
|
130
|
+
export declare function getAppDirName(spec: ClintProjectSpec): string;
|
|
48
131
|
/**
|
|
49
132
|
* Folder slug for a documentType ID. The slug is the portion after the last
|
|
50
133
|
* `/` (e.g. `powerhouse/ph-clint-project` → `ph-clint-project`). Matches the
|
package/dist/spec/types.js
CHANGED
|
@@ -9,81 +9,153 @@
|
|
|
9
9
|
* generator step actually needs it.
|
|
10
10
|
*/
|
|
11
11
|
import { z } from 'zod';
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Ordered Powerhouse integration level. Higher levels imply all lower ones:
|
|
14
|
+
* Disabled → Reactor → Switchboard → Connect
|
|
15
|
+
*/
|
|
16
|
+
export const POWERHOUSE_LEVELS = [
|
|
17
|
+
'Disabled',
|
|
18
|
+
'Reactor',
|
|
19
|
+
'Switchboard',
|
|
20
|
+
'Connect',
|
|
21
|
+
];
|
|
22
|
+
export const powerhouseLevelSchema = z
|
|
23
|
+
.enum(POWERHOUSE_LEVELS)
|
|
24
|
+
.default('Disabled');
|
|
25
|
+
/** Check whether `level` is at least `threshold` in the ordered enum. */
|
|
26
|
+
export function phAtLeast(level, threshold) {
|
|
27
|
+
return (POWERHOUSE_LEVELS.indexOf(level) >= POWERHOUSE_LEVELS.indexOf(threshold));
|
|
28
|
+
}
|
|
29
|
+
export const agentModelSchema = z.object({
|
|
30
|
+
id: z.string(),
|
|
31
|
+
isDefault: z.boolean(),
|
|
32
|
+
});
|
|
33
|
+
export const agentProfileSchema = z.object({
|
|
34
|
+
id: z.string(),
|
|
35
|
+
title: z.string(),
|
|
36
|
+
content: z.string(),
|
|
37
|
+
});
|
|
38
|
+
const mastraCommonSchema = z.object({
|
|
39
|
+
enableChat: z.boolean().default(false),
|
|
16
40
|
});
|
|
17
41
|
const mastraFeatureSchema = z.object({
|
|
18
42
|
enabled: z.boolean().default(false),
|
|
43
|
+
agentId: z.string().nullable().default(null),
|
|
44
|
+
agentName: z.string().nullable().default(null),
|
|
45
|
+
agentDescription: z.string().nullable().default(null),
|
|
46
|
+
agentImage: z.string().nullable().default(null),
|
|
47
|
+
models: z.array(agentModelSchema).default([]),
|
|
48
|
+
profiles: z.array(agentProfileSchema).default([]),
|
|
49
|
+
common: mastraCommonSchema.default({ enableChat: false }),
|
|
19
50
|
});
|
|
20
51
|
const routineFeatureSchema = z.object({
|
|
21
52
|
enabled: z.boolean().default(false),
|
|
22
53
|
});
|
|
23
|
-
|
|
24
|
-
// missing outer key fills in `{}`, but nested keys with their own `.default`
|
|
25
|
-
// are not re-defaulted unless the object itself re-parses. We spell out full
|
|
26
|
-
// defaults here so `clintProjectSpecSchema.parse({ name: 'x' })` yields a
|
|
27
|
-
// fully-populated feature tree.
|
|
28
|
-
const DEFAULT_POWERHOUSE = {
|
|
54
|
+
const DEFAULT_MASTRA = {
|
|
29
55
|
enabled: false,
|
|
30
|
-
|
|
31
|
-
|
|
56
|
+
agentId: null,
|
|
57
|
+
agentName: null,
|
|
58
|
+
agentDescription: null,
|
|
59
|
+
agentImage: null,
|
|
60
|
+
models: [],
|
|
61
|
+
profiles: [],
|
|
62
|
+
common: { enableChat: false },
|
|
32
63
|
};
|
|
33
|
-
const DEFAULT_MASTRA = { enabled: false };
|
|
34
64
|
const DEFAULT_ROUTINE = { enabled: false };
|
|
65
|
+
export const powerhousePackageSchema = z.object({
|
|
66
|
+
id: z.string(),
|
|
67
|
+
packageName: z.string(),
|
|
68
|
+
documentTypes: z.array(z.string()).default([]),
|
|
69
|
+
version: z.string().nullable().default(null),
|
|
70
|
+
});
|
|
71
|
+
export const externalSkillSchema = z.object({
|
|
72
|
+
id: z.string(),
|
|
73
|
+
name: z.string(),
|
|
74
|
+
githubUrl: z.string(),
|
|
75
|
+
});
|
|
35
76
|
export const clintProjectSpecSchema = z.object({
|
|
36
77
|
name: z
|
|
37
78
|
.string()
|
|
38
|
-
.regex(/^[a-z0-9][a-z0-9-]
|
|
79
|
+
.regex(/^[a-z0-9][a-z0-9-]*-cli$/, 'must end with -cli, lowercase letters, digits, hyphens only'),
|
|
39
80
|
scope: z
|
|
40
81
|
.string()
|
|
41
|
-
.regex(
|
|
82
|
+
.regex(/^@[a-z0-9][a-z0-9-]*$/, 'must start with @, lowercase letters, digits, hyphens only')
|
|
42
83
|
.optional(),
|
|
43
|
-
version: z.string().default('0.1.0'),
|
|
84
|
+
version: z.string().default('0.0.1-dev.0'),
|
|
44
85
|
description: z.string().default(''),
|
|
45
|
-
bin: z.string().optional(),
|
|
46
86
|
features: z
|
|
47
87
|
.object({
|
|
48
|
-
powerhouse:
|
|
88
|
+
powerhouse: powerhouseLevelSchema,
|
|
49
89
|
mastra: mastraFeatureSchema.default(DEFAULT_MASTRA),
|
|
50
90
|
routine: routineFeatureSchema.default(DEFAULT_ROUTINE),
|
|
51
91
|
})
|
|
52
92
|
.default({
|
|
53
|
-
powerhouse:
|
|
93
|
+
powerhouse: 'Disabled',
|
|
54
94
|
mastra: DEFAULT_MASTRA,
|
|
55
95
|
routine: DEFAULT_ROUTINE,
|
|
56
96
|
}),
|
|
57
97
|
/**
|
|
58
|
-
*
|
|
59
|
-
*
|
|
60
|
-
*
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
* package.
|
|
98
|
+
* Reactor packages and their document types. Each entry groups a package
|
|
99
|
+
* name with the document type IDs it provides. The app package (project's
|
|
100
|
+
* own reactor package) uses a `file:` dependency; external packages become
|
|
101
|
+
* versioned npm dependencies. Drives codegen of `framework.gen.ts`,
|
|
102
|
+
* `app/index.ts`, and `cli/package.json`.
|
|
64
103
|
*/
|
|
65
|
-
|
|
104
|
+
packages: z.array(powerhousePackageSchema).default([]),
|
|
105
|
+
/**
|
|
106
|
+
* External skills from the skills.sh ecosystem. Each skill has a name
|
|
107
|
+
* (kebab-case) and a GitHub URL for installation.
|
|
108
|
+
*/
|
|
109
|
+
externalSkills: z.array(externalSkillSchema).default([]),
|
|
110
|
+
deployment: z.object({
|
|
111
|
+
proxyEnabled: z.boolean().default(false),
|
|
112
|
+
supportedResources: z.array(z.string()).default([]),
|
|
113
|
+
}).default({ proxyEnabled: false, supportedResources: [] }),
|
|
114
|
+
/** ID of the source specification document (if backed by a Powerhouse document). */
|
|
115
|
+
documentId: z.string().optional(),
|
|
116
|
+
/** Document type of the source specification document. */
|
|
117
|
+
documentType: z.string().optional(),
|
|
66
118
|
});
|
|
67
|
-
/** npm package name (e.g. `@scope/
|
|
119
|
+
/** npm package name (e.g. `@scope/my-tool-cli` or `my-tool-cli`). */
|
|
68
120
|
export function getPackageName(spec) {
|
|
69
|
-
return spec.scope ?
|
|
121
|
+
return spec.scope ? `${spec.scope}/${spec.name}` : spec.name;
|
|
70
122
|
}
|
|
71
|
-
/** bin name (
|
|
123
|
+
/** bin name (strips -cli suffix, e.g. `my-tool-cli` → `my-tool`). */
|
|
72
124
|
export function getBinName(spec) {
|
|
73
|
-
return spec.
|
|
125
|
+
return spec.name.replace(/-cli$/, '');
|
|
74
126
|
}
|
|
75
127
|
/**
|
|
76
128
|
* Name of the CLI sub-folder when the project is split (Powerhouse enabled).
|
|
77
129
|
* For flat projects this is irrelevant — callers use the project root directly.
|
|
78
130
|
*/
|
|
79
131
|
export function getCliFolderName(spec) {
|
|
80
|
-
return
|
|
132
|
+
return spec.name;
|
|
81
133
|
}
|
|
82
134
|
/**
|
|
83
135
|
* Name of the reactor-package sub-folder when the project is split.
|
|
84
136
|
*/
|
|
85
137
|
export function getAppFolderName(spec) {
|
|
86
|
-
return
|
|
138
|
+
return spec.name.replace(/-cli$/, '-app');
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Flat list of all document types across all packages. Convenience for
|
|
142
|
+
* codegen that needs to iterate every registered document type regardless
|
|
143
|
+
* of which package provides it.
|
|
144
|
+
*/
|
|
145
|
+
export function getAllDocumentTypes(spec) {
|
|
146
|
+
return spec.packages.flatMap((p) => p.documentTypes);
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The app npm package name (`@scope/my-tool-app` or `my-tool-app`).
|
|
150
|
+
* Matches what the document model reducer stores in `packages[].packageName`.
|
|
151
|
+
*/
|
|
152
|
+
export function getAppPackageName(spec) {
|
|
153
|
+
const base = getAppFolderName(spec);
|
|
154
|
+
return spec.scope ? `${spec.scope}/${base}` : base;
|
|
155
|
+
}
|
|
156
|
+
/** Directory name for the app package (e.g. `my-tool-app`, no scope prefix). */
|
|
157
|
+
export function getAppDirName(spec) {
|
|
158
|
+
return getAppFolderName(spec);
|
|
87
159
|
}
|
|
88
160
|
/**
|
|
89
161
|
* Folder slug for a documentType ID. The slug is the portion after the last
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/** Map document model PublishTag values to CLI --tag values. */
|
|
2
|
+
export declare function tagToCli(tag: string): 'dev' | 'staging' | 'production' | null;
|
|
3
|
+
export declare const publishTrigger: import("@powerhousedao/ph-clint").Trigger<{
|
|
4
|
+
pending: number;
|
|
5
|
+
}, {
|
|
6
|
+
model: string;
|
|
7
|
+
devServicePort: number;
|
|
8
|
+
phVersion: string;
|
|
9
|
+
apiKey?: string | undefined;
|
|
10
|
+
}, import("@powerhousedao/ph-clint").InferRegistry<readonly [import("document-model").DocumentModelModule<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>]>>;
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `publish-trigger` — watches ALL `powerhouse/ph-clint-project` documents for
|
|
3
|
+
* publish records with `Pending` status and invokes the publish pipeline.
|
|
4
|
+
*
|
|
5
|
+
* Unlike `spec-change`, this trigger does NOT convert to a `ClintProjectSpec`.
|
|
6
|
+
* It reads `publishHistory` directly from the document state, since publish
|
|
7
|
+
* records are a doc-model concern (not a codegen input).
|
|
8
|
+
*
|
|
9
|
+
* Uses the multi-doc path (no `documentId`), scanning all matching documents
|
|
10
|
+
* on each poll. For each document with a pending publish record, it uses the
|
|
11
|
+
* project mapping to resolve the on-disk project directory.
|
|
12
|
+
*
|
|
13
|
+
* Flow:
|
|
14
|
+
* 1. On document change, scans `publishHistory` for records with status
|
|
15
|
+
* `"Pending"`.
|
|
16
|
+
* 2. For each pending record, returns a work item that:
|
|
17
|
+
* a. Dispatches SET_PUBLISH_STATUS({ id, status: "InProgress" }).
|
|
18
|
+
* b. Runs `ph-clint clint-project-publish --tag <tag>`.
|
|
19
|
+
* c. Dispatches SET_PUBLISH_STATUS({ id, status: "Succeeded"|"Failed" }).
|
|
20
|
+
*/
|
|
21
|
+
import { spawn } from 'node:child_process';
|
|
22
|
+
import path from 'node:path';
|
|
23
|
+
import { scanProjects, getProjectMapping } from '@powerhousedao/ph-clint';
|
|
24
|
+
import { setPublishStatus } from '@powerhousedao/ph-clint-app';
|
|
25
|
+
import { createDocumentChangeTrigger } from '../framework.js';
|
|
26
|
+
import { specFromDocumentState } from '../spec/from-document.js';
|
|
27
|
+
import { clintProject } from '../services/clint-project.js';
|
|
28
|
+
const DOCUMENT_TYPE = 'powerhouse/ph-clint-project';
|
|
29
|
+
const TAG = '[publish]';
|
|
30
|
+
/** Run a shell command and return stdout. Rejects on non-zero exit. */
|
|
31
|
+
function exec(cmd, args, cwd, onLog) {
|
|
32
|
+
return new Promise((resolve, reject) => {
|
|
33
|
+
const proc = spawn(cmd, args, { cwd, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
34
|
+
const out = [];
|
|
35
|
+
const err = [];
|
|
36
|
+
proc.stdout?.on('data', (d) => {
|
|
37
|
+
const s = d.toString();
|
|
38
|
+
out.push(s);
|
|
39
|
+
if (onLog)
|
|
40
|
+
for (const line of s.split('\n'))
|
|
41
|
+
if (line.trim())
|
|
42
|
+
onLog(line.trim());
|
|
43
|
+
});
|
|
44
|
+
proc.stderr?.on('data', (d) => {
|
|
45
|
+
const s = d.toString();
|
|
46
|
+
err.push(s);
|
|
47
|
+
if (onLog)
|
|
48
|
+
for (const line of s.split('\n'))
|
|
49
|
+
if (line.trim())
|
|
50
|
+
onLog(line.trim());
|
|
51
|
+
});
|
|
52
|
+
proc.on('error', reject);
|
|
53
|
+
proc.on('close', (code) => {
|
|
54
|
+
if (code === 0)
|
|
55
|
+
resolve(out.join(''));
|
|
56
|
+
else
|
|
57
|
+
reject(new Error(`${cmd} ${args.join(' ')} exited ${code}\n${err.join('')}`));
|
|
58
|
+
});
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
/** Map document model PublishTag values to CLI --tag values. */
|
|
62
|
+
export function tagToCli(tag) {
|
|
63
|
+
switch (tag) {
|
|
64
|
+
case 'Dev':
|
|
65
|
+
return 'dev';
|
|
66
|
+
case 'Staging':
|
|
67
|
+
return 'staging';
|
|
68
|
+
case 'Production':
|
|
69
|
+
return 'production';
|
|
70
|
+
default:
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
export const publishTrigger = createDocumentChangeTrigger({
|
|
75
|
+
id: 'publish-trigger',
|
|
76
|
+
documentType: DOCUMENT_TYPE,
|
|
77
|
+
// No documentId → watches ALL ph-clint-project docs
|
|
78
|
+
// Don't fire on startup — only react to new pending records.
|
|
79
|
+
initialReconcile: false,
|
|
80
|
+
async onChange(docs, ctx) {
|
|
81
|
+
const log = ctx.context.log;
|
|
82
|
+
const folders = ctx.context.folders;
|
|
83
|
+
// Build the mapping to resolve on-disk project directories
|
|
84
|
+
const scanner = clintProject.projectScanner;
|
|
85
|
+
const scanResults = scanner
|
|
86
|
+
? scanProjects(ctx.context.workdir, scanner)
|
|
87
|
+
: [];
|
|
88
|
+
const mapping = await getProjectMapping(scanResults, folders);
|
|
89
|
+
for (const doc of docs) {
|
|
90
|
+
const publishHistory = doc.state.global.publishHistory ?? [];
|
|
91
|
+
const pending = publishHistory.filter((r) => r.status === 'Pending');
|
|
92
|
+
if (pending.length === 0)
|
|
93
|
+
continue;
|
|
94
|
+
// Resolve the on-disk target directory for this document
|
|
95
|
+
const spec = specFromDocumentState(doc.state.global, {
|
|
96
|
+
documentId: doc.header.id,
|
|
97
|
+
documentType: doc.header.documentType,
|
|
98
|
+
});
|
|
99
|
+
const entry = mapping.find((m) => m.documentId === doc.header.id);
|
|
100
|
+
const workdir = entry?.path
|
|
101
|
+
?? (spec ? path.join(ctx.context.workdir, spec.name) : ctx.context.workdir);
|
|
102
|
+
// Process the first pending record (one per tick to avoid races).
|
|
103
|
+
const record = pending[0];
|
|
104
|
+
const cliTag = tagToCli(record.tag);
|
|
105
|
+
if (!cliTag) {
|
|
106
|
+
log?.warn(`${TAG} unknown publish tag "${record.tag}" for record ${record.id}`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
log?.info(`${TAG} found pending ${record.tag} publish for doc ${doc.header.id} (id=${record.id}, version=${record.version})`);
|
|
110
|
+
return {
|
|
111
|
+
type: 'function',
|
|
112
|
+
params: {
|
|
113
|
+
fn: async () => {
|
|
114
|
+
const reactor = await ctx.reactor();
|
|
115
|
+
if (!reactor) {
|
|
116
|
+
log?.error(`${TAG} reactor not available, cannot update publish status`);
|
|
117
|
+
return;
|
|
118
|
+
}
|
|
119
|
+
// Mark as InProgress.
|
|
120
|
+
log?.info(`${TAG} marking record ${record.id} as InProgress`);
|
|
121
|
+
await reactor.client.execute(doc.header.id, 'main', [
|
|
122
|
+
setPublishStatus({ id: record.id, status: 'InProgress' }),
|
|
123
|
+
]);
|
|
124
|
+
// Install dependencies in the generated project before publishing.
|
|
125
|
+
log?.info(`${TAG} running pnpm install in ${workdir}`);
|
|
126
|
+
try {
|
|
127
|
+
await exec('pnpm', ['install'], workdir, (msg) => log?.debug(`${TAG} [install] ${msg}`));
|
|
128
|
+
}
|
|
129
|
+
catch (installErr) {
|
|
130
|
+
log?.error(`${TAG} pnpm install failed: ${installErr instanceof Error ? installErr.message : String(installErr)}`);
|
|
131
|
+
}
|
|
132
|
+
// Run the publish command.
|
|
133
|
+
let success = false;
|
|
134
|
+
try {
|
|
135
|
+
log?.info(`${TAG} invoking clint-project-publish --tag ${cliTag}`);
|
|
136
|
+
const { clintProjectPublish } = await import('../commands/clint-project-publish.js');
|
|
137
|
+
const result = await clintProjectPublish.execute({ tag: cliTag, dryRun: false, skipBuild: false, skipGitCheck: true, verbose: false },
|
|
138
|
+
// @ts-expect-error — minimal context; publish uses workdir + stdout.
|
|
139
|
+
{
|
|
140
|
+
workdir,
|
|
141
|
+
stdout: (msg) => log?.info(`${TAG} ${msg}`),
|
|
142
|
+
log,
|
|
143
|
+
});
|
|
144
|
+
success = !result.text.includes('failed');
|
|
145
|
+
}
|
|
146
|
+
catch (err) {
|
|
147
|
+
log?.error(`${TAG} publish failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
148
|
+
}
|
|
149
|
+
// Update status.
|
|
150
|
+
const finalStatus = success ? 'Succeeded' : 'Failed';
|
|
151
|
+
log?.info(`${TAG} marking record ${record.id} as ${finalStatus}`);
|
|
152
|
+
await reactor.client.execute(doc.header.id, 'main', [
|
|
153
|
+
setPublishStatus({
|
|
154
|
+
id: record.id,
|
|
155
|
+
status: finalStatus,
|
|
156
|
+
}),
|
|
157
|
+
]);
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
callbacks: {
|
|
161
|
+
onFailure: (err) => {
|
|
162
|
+
log?.error(`${TAG} publish trigger failed: ${err.message}`);
|
|
163
|
+
},
|
|
164
|
+
},
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
return null;
|
|
168
|
+
},
|
|
169
|
+
});
|
|
@@ -1,43 +1,14 @@
|
|
|
1
|
+
import type { ImportSpecInput } from '@powerhousedao/ph-clint-app/document-models/ph-clint-project';
|
|
1
2
|
import type { ClintProjectSpec } from '../spec/types.js';
|
|
2
|
-
/** Stable hash of a ClintProjectSpec (sha256 of canonical-key JSON).
|
|
3
|
+
/** Stable hash of a ClintProjectSpec (sha256 of canonical-key JSON).
|
|
4
|
+
* Excludes documentId/documentType — they don't affect codegen output. */
|
|
3
5
|
export declare function hashSpec(spec: ClintProjectSpec): string;
|
|
6
|
+
export declare function specToImportInput(spec: ClintProjectSpec): ImportSpecInput;
|
|
4
7
|
export declare const specChangeTrigger: import("@powerhousedao/ph-clint").Trigger<{
|
|
5
8
|
pending: number;
|
|
6
9
|
}, {
|
|
7
10
|
model: string;
|
|
8
11
|
devServicePort: number;
|
|
9
12
|
phVersion: string;
|
|
10
|
-
projectDocumentId?: string | undefined;
|
|
11
13
|
apiKey?: string | undefined;
|
|
12
|
-
}, import("@powerhousedao/ph-clint").InferRegistry<readonly [
|
|
13
|
-
readonly version: 1;
|
|
14
|
-
readonly reducer: import("document-model").Reducer<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
|
|
15
|
-
readonly actions: {
|
|
16
|
-
enableRoutine: (input: import("@powerhousedao/ph-clint-app").EnableRoutineInput) => import("@powerhousedao/ph-clint-app").EnableRoutineAction;
|
|
17
|
-
disableRoutine: (input: import("@powerhousedao/ph-clint-app").DisableRoutineInput) => import("@powerhousedao/ph-clint-app").DisableRoutineAction;
|
|
18
|
-
enableMastra: (input: import("@powerhousedao/ph-clint-app").EnableMastraInput) => import("@powerhousedao/ph-clint-app").EnableMastraAction;
|
|
19
|
-
disableMastra: (input: import("@powerhousedao/ph-clint-app").DisableMastraInput) => import("@powerhousedao/ph-clint-app").DisableMastraAction;
|
|
20
|
-
enablePowerhouse: (input: import("@powerhousedao/ph-clint-app").EnablePowerhouseInput) => import("@powerhousedao/ph-clint-app").EnablePowerhouseAction;
|
|
21
|
-
setPowerhouseSwitchboard: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseSwitchboardInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseSwitchboardAction;
|
|
22
|
-
setPowerhouseConnect: (input: import("@powerhousedao/ph-clint-app").SetPowerhouseConnectInput) => import("@powerhousedao/ph-clint-app").SetPowerhouseConnectAction;
|
|
23
|
-
setPackageName: (input: import("@powerhousedao/ph-clint-app").SetPackageNameInput) => import("@powerhousedao/ph-clint-app").SetPackageNameAction;
|
|
24
|
-
clearBin: (input: import("@powerhousedao/ph-clint-app").ClearBinInput) => import("@powerhousedao/ph-clint-app").ClearBinAction;
|
|
25
|
-
setBin: (input: import("@powerhousedao/ph-clint-app").SetBinInput) => import("@powerhousedao/ph-clint-app").SetBinAction;
|
|
26
|
-
setDescription: (input: import("@powerhousedao/ph-clint-app").SetDescriptionInput) => import("@powerhousedao/ph-clint-app").SetDescriptionAction;
|
|
27
|
-
setVersion: (input: import("@powerhousedao/ph-clint-app").SetVersionInput) => import("@powerhousedao/ph-clint-app").SetVersionAction;
|
|
28
|
-
clearScope: (input: import("@powerhousedao/ph-clint-app").ClearScopeInput) => import("@powerhousedao/ph-clint-app").ClearScopeAction;
|
|
29
|
-
setScope: (input: import("@powerhousedao/ph-clint-app").SetScopeInput) => import("@powerhousedao/ph-clint-app").SetScopeAction;
|
|
30
|
-
setName: (name: string | {
|
|
31
|
-
name: string;
|
|
32
|
-
}) => import("document-model").SetNameAction;
|
|
33
|
-
undo: (count?: number, scope?: string) => import("document-model").UndoAction;
|
|
34
|
-
redo: (count?: number, scope?: string) => import("document-model").RedoAction;
|
|
35
|
-
prune: (start?: number, end?: number, scope?: string) => import("document-model").SchemaPruneAction;
|
|
36
|
-
loadState: <TState extends import("document-model").PHBaseState = import("document-model").PHBaseState>(state: TState & {
|
|
37
|
-
name: string;
|
|
38
|
-
}, operations: number) => import("document-model").LoadStateAction;
|
|
39
|
-
noop: (scope?: string) => import("document-model").NOOPAction;
|
|
40
|
-
};
|
|
41
|
-
readonly utils: import("document-model").DocumentModelUtils<import("@powerhousedao/ph-clint-app").PhClintProjectPHState>;
|
|
42
|
-
readonly documentModel: import("document-model").DocumentModelPHState;
|
|
43
|
-
}]>>;
|
|
14
|
+
}, import("@powerhousedao/ph-clint").InferRegistry<readonly [import("document-model").DocumentModelModule<import("@powerhousedao/ph-clint-app/document-models/ph-clint-project").PhClintProjectPHState>]>>;
|