@crossdelta/platform-sdk 0.21.12 → 0.21.14

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.
@@ -1,56 +1,82 @@
1
- import { join } from 'node:path'
2
1
  import {
3
- buildExternalUrls,
4
- buildIngressRules,
5
- buildInternalUrls,
6
- buildServicePortEnvs,
7
- buildServices,
8
- buildServiceUrlEnvs,
9
- discoverServices,
2
+ createDOKSCluster,
3
+ createImagePullSecret,
4
+ createNamespace,
5
+ deployK8sServices,
6
+ deployRuntime,
7
+ discoverServiceConfigs,
8
+ materializeStreams,
10
9
  } from '@crossdelta/infrastructure'
11
- import { App } from '@pulumi/digitalocean'
10
+ import * as contracts from '{{scope}}/contracts'
12
11
  import { Config, getStack } from '@pulumi/pulumi'
13
12
 
14
- const allServiceConfigs = discoverServices(join(__dirname, 'services'))
15
- const serviceConfigs = allServiceConfigs.filter((config) => !config.skip)
13
+ const stack = getStack()
16
14
  const cfg = new Config()
17
- const logtailToken = cfg.requireSecret('logtailToken')
18
15
  const registryCredentials = cfg.requireSecret('registryCredentials')
19
16
 
20
- const stack = getStack()
17
+ const namespace = `{{projectName}}-${stack}`
21
18
 
22
- const doAppName = `{{projectName}}-${stack}`
19
+ const { provider, kubeconfig, endpoint } = createDOKSCluster({
20
+ name: '{{projectName}}-cluster',
21
+ clusterName: '{{projectName}}-cluster',
22
+ region: 'fra1',
23
+ ha: false,
24
+ version: '1.32.2-do.1',
25
+ nodePool: {
26
+ name: 'default',
27
+ size: 's-2vcpu-4gb',
28
+ nodeCount: 2,
29
+ labels: { environment: stack },
30
+ },
31
+ tags: ['{{projectName}}', `env:${stack}`],
32
+ })
23
33
 
24
- const app = new App('{{projectName}}', {
25
- spec: {
26
- name: doAppName,
27
- region: 'fra',
34
+ createNamespace(provider, namespace, { environment: stack })
28
35
 
29
- alerts: [{ rule: 'DEPLOYMENT_FAILED' }, { rule: 'DOMAIN_FAILED' }],
36
+ const imagePullSecretName = 'ghcr-secret'
30
37
 
31
- features: ['buildpack-stack=ubuntu-22'],
38
+ createImagePullSecret(provider, namespace, imagePullSecretName, {
39
+ registry: 'ghcr.io',
40
+ username: 'github',
41
+ password: registryCredentials,
42
+ })
32
43
 
33
- envs: [
34
- ...buildServiceUrlEnvs(serviceConfigs),
35
- ...buildServicePortEnvs(serviceConfigs),
36
- ],
44
+ const runtime = deployRuntime(provider, namespace, {
45
+ nats: {
46
+ enabled: true,
47
+ config: {
48
+ replicas: 1,
49
+ jetstream: {
50
+ enabled: true,
51
+ storageSize: '1Gi',
52
+ storageClass: 'do-block-storage',
53
+ },
54
+ },
55
+ },
56
+ })
37
57
 
38
- services: buildServices({
39
- serviceConfigs,
40
- registryCredentials,
41
- logtailToken,
42
- }),
58
+ if (runtime.natsUrl) {
59
+ const natsDepends = runtime.natsRelease ? [runtime.natsRelease] : []
43
60
 
44
- ingress: {
45
- rules: buildIngressRules(serviceConfigs),
46
- },
61
+ materializeStreams(provider, namespace, {
62
+ natsUrl: runtime.natsUrl,
63
+ contracts,
64
+ dependsOn: natsDepends,
65
+ })
66
+ }
67
+
68
+ const serviceConfigs = discoverServiceConfigs('services').map((config) => ({
69
+ ...config,
70
+ env: {
71
+ ...config.env,
72
+ ...(runtime.natsUrl && { NATS_URL: runtime.natsUrl }),
47
73
  },
74
+ }))
75
+
76
+ deployK8sServices(provider, namespace, serviceConfigs, {
77
+ imagePullSecretName,
48
78
  })
49
79
 
50
- // Outputs
51
- export const appId = app.id
52
- export const appDefaultIngress = app.defaultIngress
53
- export const internalUrls = buildInternalUrls(serviceConfigs)
54
- export const serviceUrls = app.defaultIngress.apply((baseUrl) =>
55
- buildExternalUrls(serviceConfigs, baseUrl ?? ''),
56
- )
80
+ export const clusterEndpoint = endpoint
81
+ export const clusterKubeconfig = kubeconfig
82
+ export const natsInternalUrl = runtime.natsUrl
@@ -7,8 +7,8 @@
7
7
  "pulumi": "pulumi"
8
8
  },
9
9
  "dependencies": {
10
- "@crossdelta/cloudevents": "^0.7.20",
11
- "@crossdelta/infrastructure": "^0.11.5",
10
+ "@crossdelta/cloudevents": "^0.8.1",
11
+ "@crossdelta/infrastructure": "^0.11.7",
12
12
  "{{scope}}/contracts": "workspace:*",
13
13
  "@pulumi/digitalocean": "^4.55.0",
14
14
  "@pulumi/kubernetes": "^4.21.0",
@@ -19,8 +19,8 @@
19
19
  "clean": "rm -rf dist"
20
20
  },
21
21
  "dependencies": {
22
- "@crossdelta/cloudevents": "^0.7.20",
23
- "@crossdelta/infrastructure": "^0.11.5",
22
+ "@crossdelta/cloudevents": "^0.8.1",
23
+ "@crossdelta/infrastructure": "^0.11.7",
24
24
  "zod": "^4.0.0"
25
25
  },
26
26
  "devDependencies": {
package/dist/facade.d.mts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FlowContext, FlowRunOptions, FlowResult } from '@crossdelta/flowcore';
2
2
  export { FlowContext, FlowResult, FlowRunOptions } from '@crossdelta/flowcore';
3
- import { P as PfWorkspaceContext, g as PfEffect, a as PfPluginContext, L as LoadedPlugin, b as PfPlugin } from './plugin-types-DQOv97Zh.mjs';
4
- export { E as ElicitInputEffect, h as ElicitInputField, i as EnvAddEffect, F as FileWriteEffect, I as InfraAddEffect, c as PfCommand, d as PfCommandArg, e as PfCommandOption, j as PfCommandResult, k as isElicitInputEffect } from './plugin-types-DQOv97Zh.mjs';
3
+ import { PfWorkspaceContext, PfEffect, PfPluginContext, LoadedPlugin, PfPlugin } from '@crossdelta/shared/plugin-types';
4
+ export { ElicitInputEffect, ElicitInputField, EnvAddEffect, FileWriteEffect, InfraAddEffect, LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfCommandResult, PfEffect, PfPlugin, PfPluginContext, PfWorkspaceContext, isElicitInputEffect } from '@crossdelta/shared/plugin-types';
5
5
  export { deriveEventNames } from '@crossdelta/cloudevents';
6
6
  import { z } from 'zod';
7
7
 
@@ -837,4 +837,4 @@ declare const getGeneratorDocsDir: () => string;
837
837
  */
838
838
  declare const listGeneratorDocs: () => Promise<string[]>;
839
839
 
840
- export { type Artifact, type CapabilitiesConfig, type Change, type CodingConstraints, type CommandLikeResult, type Diagnostic, type EffectHandlerOptions, type EffectResult, type EffectRuntimeContext, type ExecutableToolSpec, type ForbiddenPattern, type FrameworkLayout, LoadedPlugin, type NextAction, type OperationResult, type ParseResult, type PathGuards, PfEffect, PfPlugin, PfPluginContext, PfWorkspaceContext, type PlannedFile, type PolicyValidationResult, type PolicyViolation, type ProviderLookup, SERVICE_LAYOUT_POLICY_VERSION, type ServiceFramework, type ServiceGenerationInputs, type ServiceMeta, type ServiceMetadata, type ServiceSpec, type ToolInputSchema, type ToolPropertySchema, type ToolSpec, aggregateChanges, applyEffects, collectExecutableToolSpecs, collectToolSpecs, createContext, createContextFromWorkspace, err as createErrResult, ok as createOkResult, findWorkspaceRoot, formatChangeDetails, formatChangeSummary, getFrameworkPolicy, getGeneratorDocsDir, getRegisteredProviders, listGeneratorDocs, loadCapabilitiesConfig, loadCapabilitiesConfigFromWorkspace, loadPlugins, lookupProvider, lowerSpecToCapabilities, parseServicePrompt, planServiceGeneration, resolveProvider, runFlow, serviceLayoutPolicy, validateGeneratedFiles };
840
+ export { type Artifact, type CapabilitiesConfig, type Change, type CodingConstraints, type CommandLikeResult, type Diagnostic, type EffectHandlerOptions, type EffectResult, type EffectRuntimeContext, type ExecutableToolSpec, type ForbiddenPattern, type FrameworkLayout, type NextAction, type OperationResult, type ParseResult, type PathGuards, type PlannedFile, type PolicyValidationResult, type PolicyViolation, type ProviderLookup, SERVICE_LAYOUT_POLICY_VERSION, type ServiceFramework, type ServiceGenerationInputs, type ServiceMeta, type ServiceMetadata, type ServiceSpec, type ToolInputSchema, type ToolPropertySchema, type ToolSpec, aggregateChanges, applyEffects, collectExecutableToolSpecs, collectToolSpecs, createContext, createContextFromWorkspace, err as createErrResult, ok as createOkResult, findWorkspaceRoot, formatChangeDetails, formatChangeSummary, getFrameworkPolicy, getGeneratorDocsDir, getRegisteredProviders, listGeneratorDocs, loadCapabilitiesConfig, loadCapabilitiesConfigFromWorkspace, loadPlugins, lookupProvider, lowerSpecToCapabilities, parseServicePrompt, planServiceGeneration, resolveProvider, runFlow, serviceLayoutPolicy, validateGeneratedFiles };
package/dist/facade.d.ts CHANGED
@@ -1,7 +1,7 @@
1
1
  import { FlowContext, FlowRunOptions, FlowResult } from '@crossdelta/flowcore';
2
2
  export { FlowContext, FlowResult, FlowRunOptions } from '@crossdelta/flowcore';
3
- import { P as PfWorkspaceContext, g as PfEffect, a as PfPluginContext, L as LoadedPlugin, b as PfPlugin } from './plugin-types-DQOv97Zh.js';
4
- export { E as ElicitInputEffect, h as ElicitInputField, i as EnvAddEffect, F as FileWriteEffect, I as InfraAddEffect, c as PfCommand, d as PfCommandArg, e as PfCommandOption, j as PfCommandResult, k as isElicitInputEffect } from './plugin-types-DQOv97Zh.js';
3
+ import { PfWorkspaceContext, PfEffect, PfPluginContext, LoadedPlugin, PfPlugin } from '@crossdelta/shared/plugin-types';
4
+ export { ElicitInputEffect, ElicitInputField, EnvAddEffect, FileWriteEffect, InfraAddEffect, LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfCommandResult, PfEffect, PfPlugin, PfPluginContext, PfWorkspaceContext, isElicitInputEffect } from '@crossdelta/shared/plugin-types';
5
5
  export { deriveEventNames } from '@crossdelta/cloudevents';
6
6
  import { z } from 'zod';
7
7
 
@@ -837,4 +837,4 @@ declare const getGeneratorDocsDir: () => string;
837
837
  */
838
838
  declare const listGeneratorDocs: () => Promise<string[]>;
839
839
 
840
- export { type Artifact, type CapabilitiesConfig, type Change, type CodingConstraints, type CommandLikeResult, type Diagnostic, type EffectHandlerOptions, type EffectResult, type EffectRuntimeContext, type ExecutableToolSpec, type ForbiddenPattern, type FrameworkLayout, LoadedPlugin, type NextAction, type OperationResult, type ParseResult, type PathGuards, PfEffect, PfPlugin, PfPluginContext, PfWorkspaceContext, type PlannedFile, type PolicyValidationResult, type PolicyViolation, type ProviderLookup, SERVICE_LAYOUT_POLICY_VERSION, type ServiceFramework, type ServiceGenerationInputs, type ServiceMeta, type ServiceMetadata, type ServiceSpec, type ToolInputSchema, type ToolPropertySchema, type ToolSpec, aggregateChanges, applyEffects, collectExecutableToolSpecs, collectToolSpecs, createContext, createContextFromWorkspace, err as createErrResult, ok as createOkResult, findWorkspaceRoot, formatChangeDetails, formatChangeSummary, getFrameworkPolicy, getGeneratorDocsDir, getRegisteredProviders, listGeneratorDocs, loadCapabilitiesConfig, loadCapabilitiesConfigFromWorkspace, loadPlugins, lookupProvider, lowerSpecToCapabilities, parseServicePrompt, planServiceGeneration, resolveProvider, runFlow, serviceLayoutPolicy, validateGeneratedFiles };
840
+ export { type Artifact, type CapabilitiesConfig, type Change, type CodingConstraints, type CommandLikeResult, type Diagnostic, type EffectHandlerOptions, type EffectResult, type EffectRuntimeContext, type ExecutableToolSpec, type ForbiddenPattern, type FrameworkLayout, type NextAction, type OperationResult, type ParseResult, type PathGuards, type PlannedFile, type PolicyValidationResult, type PolicyViolation, type ProviderLookup, SERVICE_LAYOUT_POLICY_VERSION, type ServiceFramework, type ServiceGenerationInputs, type ServiceMeta, type ServiceMetadata, type ServiceSpec, type ToolInputSchema, type ToolPropertySchema, type ToolSpec, aggregateChanges, applyEffects, collectExecutableToolSpecs, collectToolSpecs, createContext, createContextFromWorkspace, err as createErrResult, ok as createOkResult, findWorkspaceRoot, formatChangeDetails, formatChangeSummary, getFrameworkPolicy, getGeneratorDocsDir, getRegisteredProviders, listGeneratorDocs, loadCapabilitiesConfig, loadCapabilitiesConfigFromWorkspace, loadPlugins, lookupProvider, lowerSpecToCapabilities, parseServicePrompt, planServiceGeneration, resolveProvider, runFlow, serviceLayoutPolicy, validateGeneratedFiles };
package/dist/facade.js CHANGED
@@ -383,7 +383,7 @@ __export(facade_exports, {
383
383
  getFrameworkPolicy: () => getFrameworkPolicy,
384
384
  getGeneratorDocsDir: () => getGeneratorDocsDir,
385
385
  getRegisteredProviders: () => getRegisteredProviders,
386
- isElicitInputEffect: () => isElicitInputEffect,
386
+ isElicitInputEffect: () => import_plugin_types.isElicitInputEffect,
387
387
  listGeneratorDocs: () => listGeneratorDocs,
388
388
  loadCapabilitiesConfig: () => loadCapabilitiesConfig,
389
389
  loadCapabilitiesConfigFromWorkspace: () => loadCapabilitiesConfigFromWorkspace,
@@ -2166,7 +2166,7 @@ var planServiceGeneration = (inputs) => {
2166
2166
  init_config();
2167
2167
 
2168
2168
  // cli/src/core/plugins/types.ts
2169
- var isElicitInputEffect = (effect) => effect.kind === "elicit:input";
2169
+ var import_plugin_types = require("@crossdelta/shared/plugin-types");
2170
2170
 
2171
2171
  // cli/src/core/facade/context.ts
2172
2172
  init_config();
package/dist/facade.mjs CHANGED
@@ -2095,7 +2095,9 @@ var planServiceGeneration = (inputs) => {
2095
2095
  init_config();
2096
2096
 
2097
2097
  // cli/src/core/plugins/types.ts
2098
- var isElicitInputEffect = (effect) => effect.kind === "elicit:input";
2098
+ import {
2099
+ isElicitInputEffect
2100
+ } from "@crossdelta/shared/plugin-types";
2099
2101
 
2100
2102
  // cli/src/core/facade/context.ts
2101
2103
  init_config();
@@ -1 +1 @@
1
- export { L as LoadedPlugin, c as PfCommand, d as PfCommandArg, e as PfCommandOption, f as PfFlow, b as PfPlugin, a as PfPluginContext } from './plugin-types-DQOv97Zh.mjs';
1
+ export { LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfFlow, PfPlugin, PfPluginContext } from '@crossdelta/shared/plugin-types';
@@ -1 +1 @@
1
- export { L as LoadedPlugin, c as PfCommand, d as PfCommandArg, e as PfCommandOption, f as PfFlow, b as PfPlugin, a as PfPluginContext } from './plugin-types-DQOv97Zh.js';
1
+ export { LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfFlow, PfPlugin, PfPluginContext } from '@crossdelta/shared/plugin-types';
package/dist/plugin.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PfWorkspaceContext, a as PfPluginContext, L as LoadedPlugin, b as PfPlugin } from './plugin-types-DQOv97Zh.mjs';
2
- export { c as PfCommand, d as PfCommandArg, e as PfCommandOption, f as PfFlow } from './plugin-types-DQOv97Zh.mjs';
1
+ import { PfWorkspaceContext, PfPluginContext, LoadedPlugin, PfPlugin } from '@crossdelta/shared/plugin-types';
2
+ export { LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfFlow, PfPlugin, PfPluginContext, PfWorkspaceContext } from '@crossdelta/shared/plugin-types';
3
3
 
4
4
  /**
5
5
  * Plugin Loader
@@ -28,4 +28,4 @@ declare const createPluginContext: (workspace: PfWorkspaceContext, logger?: PfPl
28
28
  */
29
29
  declare const loadPluginFromModule: (moduleName: string, context: PfPluginContext) => Promise<LoadedPlugin>;
30
30
 
31
- export { LoadedPlugin, PfPlugin, PfPluginContext, PfWorkspaceContext, createPluginContext, loadPluginFromModule, validatePlugin, validatePluginStrict };
31
+ export { createPluginContext, loadPluginFromModule, validatePlugin, validatePluginStrict };
package/dist/plugin.d.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { P as PfWorkspaceContext, a as PfPluginContext, L as LoadedPlugin, b as PfPlugin } from './plugin-types-DQOv97Zh.js';
2
- export { c as PfCommand, d as PfCommandArg, e as PfCommandOption, f as PfFlow } from './plugin-types-DQOv97Zh.js';
1
+ import { PfWorkspaceContext, PfPluginContext, LoadedPlugin, PfPlugin } from '@crossdelta/shared/plugin-types';
2
+ export { LoadedPlugin, PfCommand, PfCommandArg, PfCommandOption, PfFlow, PfPlugin, PfPluginContext, PfWorkspaceContext } from '@crossdelta/shared/plugin-types';
3
3
 
4
4
  /**
5
5
  * Plugin Loader
@@ -28,4 +28,4 @@ declare const createPluginContext: (workspace: PfWorkspaceContext, logger?: PfPl
28
28
  */
29
29
  declare const loadPluginFromModule: (moduleName: string, context: PfPluginContext) => Promise<LoadedPlugin>;
30
30
 
31
- export { LoadedPlugin, PfPlugin, PfPluginContext, PfWorkspaceContext, createPluginContext, loadPluginFromModule, validatePlugin, validatePluginStrict };
31
+ export { createPluginContext, loadPluginFromModule, validatePlugin, validatePluginStrict };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crossdelta/platform-sdk",
3
- "version": "0.21.12",
3
+ "version": "0.21.14",
4
4
  "description": "Platform toolkit for event-driven microservices — keeping code and infrastructure in lockstep.",
5
5
  "keywords": [
6
6
  "cli",
@@ -118,8 +118,9 @@
118
118
  "@ai-sdk/anthropic": "^2.0.53",
119
119
  "@ai-sdk/openai": "^2.0.79",
120
120
  "@angular-devkit/core": "^21.0.0",
121
- "@crossdelta/cloudevents": "^0.7.20",
121
+ "@crossdelta/cloudevents": "^0.8.1",
122
122
  "@crossdelta/flowcore": "^0.1.2",
123
+ "@crossdelta/shared": "^0.1.0",
123
124
  "@faker-js/faker": "^9.8.0",
124
125
  "@inquirer/prompts": "^7.5.0",
125
126
  "@listr2/prompt-adapter-enquirer": "^2.0.15",
@@ -144,7 +145,7 @@
144
145
  "zod": "^4.0.0"
145
146
  },
146
147
  "peerDependencies": {
147
- "@crossdelta/infrastructure": "^0.11.5",
148
+ "@crossdelta/infrastructure": "^0.11.7",
148
149
  "@nestjs/schematics": "^11.0.5",
149
150
  "turbo": "^2.0.0"
150
151
  },
@@ -1,180 +0,0 @@
1
- /**
2
- * Plugin System Types
3
- *
4
- * pf owns and defines these interfaces.
5
- * Plugins MUST adapt to these interfaces.
6
- * pf is strict and predictable - no duck-typing, no fallbacks.
7
- */
8
- /**
9
- * Base effect type - all domain effects must have a kind
10
- * pf handles effects generically via kind-based handler registry
11
- */
12
- interface PfEffect {
13
- readonly kind: string;
14
- }
15
- /**
16
- * File write effect - write content to a file
17
- */
18
- interface FileWriteEffect extends PfEffect {
19
- readonly kind: 'file:write';
20
- readonly path: string;
21
- readonly content: string;
22
- }
23
- /**
24
- * Infrastructure service configuration effect
25
- */
26
- interface InfraAddEffect extends PfEffect {
27
- readonly kind: 'infra:add';
28
- readonly serviceName: string;
29
- readonly port: number;
30
- readonly framework: string;
31
- readonly runtime: string;
32
- }
33
- /**
34
- * Environment variable effect
35
- */
36
- interface EnvAddEffect extends PfEffect {
37
- readonly kind: 'env:add';
38
- readonly key: string;
39
- readonly value: string;
40
- }
41
- /**
42
- * Field definition for input elicitation
43
- *
44
- * Describes a single field that needs user input.
45
- * Host-agnostic - CLI and MCP interpret this differently.
46
- */
47
- interface ElicitInputField {
48
- /** Field name (used as key in response) */
49
- readonly name: string;
50
- /** Human-readable prompt/question */
51
- readonly prompt: string;
52
- /** Whether the field is required */
53
- readonly required?: boolean;
54
- /** Detailed description (shown as help text) */
55
- readonly description?: string;
56
- /** Default value if user provides nothing */
57
- readonly defaultValue?: unknown;
58
- /** Allowed values (enum constraint) */
59
- readonly enum?: readonly string[];
60
- /** Field type hint */
61
- readonly type?: 'string' | 'number' | 'boolean';
62
- }
63
- /**
64
- * Input elicitation effect
65
- *
66
- * Returned by tools when required inputs are missing.
67
- * Pure data - no MCP SDK imports, no host-specific logic.
68
- *
69
- * Hosts interpret this effect differently:
70
- * - CLI: Interactive prompt
71
- * - MCP: server.elicitInput() or structured error
72
- */
73
- interface ElicitInputEffect extends PfEffect {
74
- readonly kind: 'elicit:input';
75
- /** Message explaining what's needed */
76
- readonly message: string;
77
- /** Fields to collect from user */
78
- readonly fields: readonly ElicitInputField[];
79
- }
80
- /**
81
- * Type guard for ElicitInputEffect
82
- */
83
- declare const isElicitInputEffect: (effect: PfEffect) => effect is ElicitInputEffect;
84
- /**
85
- * Result of running a command
86
- */
87
- interface PfCommandResult {
88
- /** Domain effects to be applied by the runtime */
89
- effects: PfEffect[];
90
- /** Optional output to display (for read-only commands) */
91
- output?: string | string[];
92
- }
93
- /**
94
- * Command argument definition
95
- */
96
- interface PfCommandArg {
97
- name: string;
98
- description: string;
99
- required: boolean;
100
- }
101
- /**
102
- * Command option definition
103
- */
104
- interface PfCommandOption {
105
- flags: string;
106
- description: string;
107
- default?: unknown;
108
- }
109
- /**
110
- * A CLI command provided by a plugin
111
- *
112
- * Plugins MUST implement this exact interface.
113
- */
114
- interface PfCommand {
115
- name: string;
116
- description: string;
117
- args: PfCommandArg[];
118
- options: PfCommandOption[];
119
- run(args: Record<string, unknown>, options: Record<string, unknown>): Promise<PfCommandResult>;
120
- }
121
- /**
122
- * An interactive flow provided by a plugin
123
- */
124
- interface PfFlow {
125
- name: string;
126
- description: string;
127
- getSteps(initialContext?: Record<string, unknown>): Promise<unknown[]>;
128
- }
129
- /**
130
- * Workspace context with all discovered information
131
- * pf owns this - plugins receive it during setup
132
- */
133
- interface PfWorkspaceContext {
134
- /** Absolute path to workspace root */
135
- workspaceRoot: string;
136
- /** Discovered services (relative paths like 'services/api-gateway') */
137
- availableServices: string[];
138
- /** Contracts package configuration */
139
- contracts: {
140
- /** Relative path to contracts source (e.g., 'packages/contracts/src') */
141
- path: string;
142
- /** Package name (e.g., '@my-platform/contracts') */
143
- packageName?: string;
144
- };
145
- }
146
- /**
147
- * Plugin context provided by pf during setup
148
- */
149
- interface PfPluginContext {
150
- workspace: PfWorkspaceContext;
151
- logger: {
152
- debug: (message: string) => void;
153
- info: (message: string) => void;
154
- warn: (message: string) => void;
155
- error: (message: string) => void;
156
- };
157
- }
158
- /**
159
- * A plugin that can be loaded by pf
160
- *
161
- * Plugins MUST implement this exact interface.
162
- * If a plugin has a different internal API, it must provide an adapter.
163
- */
164
- interface PfPlugin {
165
- name: string;
166
- version: string;
167
- description?: string;
168
- commands: PfCommand[];
169
- flows: PfFlow[];
170
- setup: (context: PfPluginContext) => Promise<void> | void;
171
- }
172
- /**
173
- * Result of loading a plugin
174
- */
175
- interface LoadedPlugin {
176
- plugin: PfPlugin;
177
- source: string;
178
- }
179
-
180
- export { type ElicitInputEffect as E, type FileWriteEffect as F, type InfraAddEffect as I, type LoadedPlugin as L, type PfWorkspaceContext as P, type PfPluginContext as a, type PfPlugin as b, type PfCommand as c, type PfCommandArg as d, type PfCommandOption as e, type PfFlow as f, type PfEffect as g, type ElicitInputField as h, type EnvAddEffect as i, type PfCommandResult as j, isElicitInputEffect as k };
@@ -1,180 +0,0 @@
1
- /**
2
- * Plugin System Types
3
- *
4
- * pf owns and defines these interfaces.
5
- * Plugins MUST adapt to these interfaces.
6
- * pf is strict and predictable - no duck-typing, no fallbacks.
7
- */
8
- /**
9
- * Base effect type - all domain effects must have a kind
10
- * pf handles effects generically via kind-based handler registry
11
- */
12
- interface PfEffect {
13
- readonly kind: string;
14
- }
15
- /**
16
- * File write effect - write content to a file
17
- */
18
- interface FileWriteEffect extends PfEffect {
19
- readonly kind: 'file:write';
20
- readonly path: string;
21
- readonly content: string;
22
- }
23
- /**
24
- * Infrastructure service configuration effect
25
- */
26
- interface InfraAddEffect extends PfEffect {
27
- readonly kind: 'infra:add';
28
- readonly serviceName: string;
29
- readonly port: number;
30
- readonly framework: string;
31
- readonly runtime: string;
32
- }
33
- /**
34
- * Environment variable effect
35
- */
36
- interface EnvAddEffect extends PfEffect {
37
- readonly kind: 'env:add';
38
- readonly key: string;
39
- readonly value: string;
40
- }
41
- /**
42
- * Field definition for input elicitation
43
- *
44
- * Describes a single field that needs user input.
45
- * Host-agnostic - CLI and MCP interpret this differently.
46
- */
47
- interface ElicitInputField {
48
- /** Field name (used as key in response) */
49
- readonly name: string;
50
- /** Human-readable prompt/question */
51
- readonly prompt: string;
52
- /** Whether the field is required */
53
- readonly required?: boolean;
54
- /** Detailed description (shown as help text) */
55
- readonly description?: string;
56
- /** Default value if user provides nothing */
57
- readonly defaultValue?: unknown;
58
- /** Allowed values (enum constraint) */
59
- readonly enum?: readonly string[];
60
- /** Field type hint */
61
- readonly type?: 'string' | 'number' | 'boolean';
62
- }
63
- /**
64
- * Input elicitation effect
65
- *
66
- * Returned by tools when required inputs are missing.
67
- * Pure data - no MCP SDK imports, no host-specific logic.
68
- *
69
- * Hosts interpret this effect differently:
70
- * - CLI: Interactive prompt
71
- * - MCP: server.elicitInput() or structured error
72
- */
73
- interface ElicitInputEffect extends PfEffect {
74
- readonly kind: 'elicit:input';
75
- /** Message explaining what's needed */
76
- readonly message: string;
77
- /** Fields to collect from user */
78
- readonly fields: readonly ElicitInputField[];
79
- }
80
- /**
81
- * Type guard for ElicitInputEffect
82
- */
83
- declare const isElicitInputEffect: (effect: PfEffect) => effect is ElicitInputEffect;
84
- /**
85
- * Result of running a command
86
- */
87
- interface PfCommandResult {
88
- /** Domain effects to be applied by the runtime */
89
- effects: PfEffect[];
90
- /** Optional output to display (for read-only commands) */
91
- output?: string | string[];
92
- }
93
- /**
94
- * Command argument definition
95
- */
96
- interface PfCommandArg {
97
- name: string;
98
- description: string;
99
- required: boolean;
100
- }
101
- /**
102
- * Command option definition
103
- */
104
- interface PfCommandOption {
105
- flags: string;
106
- description: string;
107
- default?: unknown;
108
- }
109
- /**
110
- * A CLI command provided by a plugin
111
- *
112
- * Plugins MUST implement this exact interface.
113
- */
114
- interface PfCommand {
115
- name: string;
116
- description: string;
117
- args: PfCommandArg[];
118
- options: PfCommandOption[];
119
- run(args: Record<string, unknown>, options: Record<string, unknown>): Promise<PfCommandResult>;
120
- }
121
- /**
122
- * An interactive flow provided by a plugin
123
- */
124
- interface PfFlow {
125
- name: string;
126
- description: string;
127
- getSteps(initialContext?: Record<string, unknown>): Promise<unknown[]>;
128
- }
129
- /**
130
- * Workspace context with all discovered information
131
- * pf owns this - plugins receive it during setup
132
- */
133
- interface PfWorkspaceContext {
134
- /** Absolute path to workspace root */
135
- workspaceRoot: string;
136
- /** Discovered services (relative paths like 'services/api-gateway') */
137
- availableServices: string[];
138
- /** Contracts package configuration */
139
- contracts: {
140
- /** Relative path to contracts source (e.g., 'packages/contracts/src') */
141
- path: string;
142
- /** Package name (e.g., '@my-platform/contracts') */
143
- packageName?: string;
144
- };
145
- }
146
- /**
147
- * Plugin context provided by pf during setup
148
- */
149
- interface PfPluginContext {
150
- workspace: PfWorkspaceContext;
151
- logger: {
152
- debug: (message: string) => void;
153
- info: (message: string) => void;
154
- warn: (message: string) => void;
155
- error: (message: string) => void;
156
- };
157
- }
158
- /**
159
- * A plugin that can be loaded by pf
160
- *
161
- * Plugins MUST implement this exact interface.
162
- * If a plugin has a different internal API, it must provide an adapter.
163
- */
164
- interface PfPlugin {
165
- name: string;
166
- version: string;
167
- description?: string;
168
- commands: PfCommand[];
169
- flows: PfFlow[];
170
- setup: (context: PfPluginContext) => Promise<void> | void;
171
- }
172
- /**
173
- * Result of loading a plugin
174
- */
175
- interface LoadedPlugin {
176
- plugin: PfPlugin;
177
- source: string;
178
- }
179
-
180
- export { type ElicitInputEffect as E, type FileWriteEffect as F, type InfraAddEffect as I, type LoadedPlugin as L, type PfWorkspaceContext as P, type PfPluginContext as a, type PfPlugin as b, type PfCommand as c, type PfCommandArg as d, type PfCommandOption as e, type PfFlow as f, type PfEffect as g, type ElicitInputField as h, type EnvAddEffect as i, type PfCommandResult as j, isElicitInputEffect as k };