@siglo/cli 0.0.0-stage → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,319 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.toMermaid = toMermaid;
37
+ exports.toTextGraph = toTextGraph;
38
+ exports.visualizeWorkflow = visualizeWorkflow;
39
+ exports.validateWorkflow = validateWorkflow;
40
+ exports.inspectWorkflow = inspectWorkflow;
41
+ exports.replayFixture = replayFixture;
42
+ exports.inspectCheckpoint = inspectCheckpoint;
43
+ exports.initProject = initProject;
44
+ exports.generateWorkflow = generateWorkflow;
45
+ exports.generateStep = generateStep;
46
+ exports.exportWorkflow = exportWorkflow;
47
+ exports.startMonitor = startMonitor;
48
+ exports.reconcileCommand = reconcileCommand;
49
+ const step_templates_1 = require("./step-templates");
50
+ const fs = __importStar(require("fs"));
51
+ const path = __importStar(require("path"));
52
+ const core_1 = require("@siglo/core");
53
+ /**
54
+ * Renders a GraphInspectionResult as a Mermaid flowchart diagram.
55
+ */
56
+ function toMermaid(inspection) {
57
+ const lines = ['flowchart TD'];
58
+ for (const node of inspection.nodes) {
59
+ lines.push(` ${node.id}["${node.name} (${node.type})"]`);
60
+ }
61
+ for (const edge of inspection.edges) {
62
+ if (edge.label) {
63
+ lines.push(` ${edge.from} -->|${edge.label}| ${edge.to}`);
64
+ }
65
+ else {
66
+ lines.push(` ${edge.from} --> ${edge.to}`);
67
+ }
68
+ }
69
+ return lines.join('\n');
70
+ }
71
+ /**
72
+ * Renders a GraphInspectionResult as an indented ASCII text tree diagram.
73
+ */
74
+ function toTextGraph(inspection) {
75
+ const lines = [`Workflow Graph (total nodes: ${inspection.totalNodes}, edges: ${inspection.edges.length}):`];
76
+ for (let i = 0; i < inspection.nodes.length; i++) {
77
+ const node = inspection.nodes[i];
78
+ const isLast = i === inspection.nodes.length - 1;
79
+ const prefix = isLast ? '└── ' : '├── ';
80
+ lines.push(`${prefix}[${node.type}] ${node.name} (${node.id})`);
81
+ }
82
+ return lines.join('\n');
83
+ }
84
+ /**
85
+ * Visualizes a siglo workflow graph as Mermaid and text flowchart representations.
86
+ */
87
+ function visualizeWorkflow(workflow) {
88
+ const graph = (0, core_1.toGraph)(workflow);
89
+ const inspection = (0, core_1.inspectGraph)(workflow);
90
+ const validation = (0, core_1.validateGraph)(graph);
91
+ return {
92
+ mermaid: toMermaid(inspection),
93
+ text: toTextGraph(inspection),
94
+ nodeCount: inspection.totalNodes,
95
+ hasCycles: !validation.valid,
96
+ };
97
+ }
98
+ /**
99
+ * Statically validates a workflow graph definition.
100
+ */
101
+ function validateWorkflow(workflow) {
102
+ const graph = (0, core_1.toGraph)(workflow);
103
+ return (0, core_1.validateGraph)(graph);
104
+ }
105
+ /**
106
+ * Returns a diagnostic inspection report for a workflow with optional field redaction.
107
+ */
108
+ function inspectWorkflow(workflow, options = {}) {
109
+ const inspection = (0, core_1.inspectGraph)(workflow);
110
+ const redactedFields = options.redact || [];
111
+ if (redactedFields.length > 0) {
112
+ const sanitizedNodes = inspection.nodes.map((n) => {
113
+ if (redactedFields.includes(n.name)) {
114
+ return { ...n, name: '[REDACTED]' };
115
+ }
116
+ return n;
117
+ });
118
+ return {
119
+ ...inspection,
120
+ nodes: sanitizedNodes,
121
+ redactedFields,
122
+ };
123
+ }
124
+ return inspection;
125
+ }
126
+ /**
127
+ * Replays a workflow execution against a recorded test fixture.
128
+ */
129
+ async function replayFixture(workflow, fixture) {
130
+ const parsedFixture = typeof fixture === 'string'
131
+ ? JSON.parse(fs.readFileSync(fixture, 'utf-8'))
132
+ : fixture;
133
+ const startTime = Date.now();
134
+ const result = await workflow.run(parsedFixture.initialParam, { pojo: true });
135
+ const durationMs = Date.now() - startTime;
136
+ let success = true;
137
+ const diff = {};
138
+ if (parsedFixture.expectedOutputs) {
139
+ for (const [key, expectedVal] of Object.entries(parsedFixture.expectedOutputs)) {
140
+ const actualVal = result[key];
141
+ if (JSON.stringify(actualVal) !== JSON.stringify(expectedVal)) {
142
+ success = false;
143
+ diff[key] = { expected: expectedVal, actual: actualVal };
144
+ }
145
+ }
146
+ }
147
+ return {
148
+ success,
149
+ durationMs,
150
+ finalContext: result,
151
+ diff: Object.keys(diff).length > 0 ? diff : undefined,
152
+ };
153
+ }
154
+ /**
155
+ * Inspects a serialized checkpoint with optional field redaction.
156
+ */
157
+ function inspectCheckpoint(checkpoint, options = {}) {
158
+ const parsed = typeof checkpoint === 'string'
159
+ ? JSON.parse(checkpoint)
160
+ : checkpoint;
161
+ const redactKeys = options.redact || [];
162
+ const contexts = { ...(parsed.contexts || {}) };
163
+ if (redactKeys.length > 0) {
164
+ for (const stepId of Object.keys(contexts)) {
165
+ const stepCtx = { ...contexts[stepId] };
166
+ for (const key of Object.keys(stepCtx)) {
167
+ if (redactKeys.includes(key)) {
168
+ stepCtx[key] = '[REDACTED]';
169
+ }
170
+ }
171
+ contexts[stepId] = stepCtx;
172
+ }
173
+ }
174
+ return {
175
+ stackId: parsed.stackId,
176
+ namespace: parsed.namespace,
177
+ type: parsed.type,
178
+ stepCount: parsed.chains?.length || 0,
179
+ chains: parsed.chains,
180
+ contexts,
181
+ };
182
+ }
183
+ /**
184
+ * Scaffolds a new starter siglo project directory.
185
+ */
186
+ function initProject(targetDir = process.cwd()) {
187
+ const srcDir = path.join(targetDir, 'src');
188
+ fs.mkdirSync(srcDir, { recursive: true });
189
+ const packageJsonPath = path.join(targetDir, 'package.json');
190
+ const workflowPath = path.join(srcDir, 'workflow.ts');
191
+ const testPath = path.join(srcDir, 'workflow.test.ts');
192
+ const filesCreated = [];
193
+ if (!fs.existsSync(packageJsonPath)) {
194
+ const pkg = {
195
+ name: 'my-siglo-workflow',
196
+ version: '1.0.0',
197
+ description: 'Starter project built with siglo workflow runtime',
198
+ scripts: {
199
+ test: 'tsx --test src/**/*.test.ts',
200
+ start: 'tsx src/workflow.ts',
201
+ },
202
+ dependencies: {
203
+ '@siglo/core': '^1.0.0',
204
+ },
205
+ devDependencies: {
206
+ '@siglo/testing': '^1.0.0',
207
+ '@types/node': '^22.0.0',
208
+ chai: '^5.0.0',
209
+ tsx: '^4.0.0',
210
+ typescript: '~5.7.0',
211
+ },
212
+ };
213
+ fs.writeFileSync(packageJsonPath, JSON.stringify(pkg, null, 2));
214
+ filesCreated.push(packageJsonPath);
215
+ }
216
+ if (!fs.existsSync(workflowPath)) {
217
+ const code = `import { Step, flow } from '@siglo/core';\n\nexport interface OrderInput {\n orderId: string;\n amount: number;\n}\n\nexport function createOrderWorkflow() {\n const validateOrder = Step.create('validateOrder', async ({ orderId, amount }: any) => {\n if (!orderId) throw new Error('Missing orderId');\n return { validated: true, orderId, amount };\n });\n\n const processPayment = Step.create('processPayment', async ({ amount }: any) => {\n return { paymentStatus: 'CHARGED', amountCharged: amount };\n });\n\n return flow(validateOrder, processPayment);\n}\n`;
218
+ fs.writeFileSync(workflowPath, code);
219
+ filesCreated.push(workflowPath);
220
+ }
221
+ if (!fs.existsSync(testPath)) {
222
+ const testCode = `import test from 'node:test';\nimport assert from 'node:assert/strict';\nimport { createOrderWorkflow } from './workflow';\n\ntest('Order workflow executes successfully', async () => {\n const workflow = createOrderWorkflow();\n const result = await workflow.run({ orderId: 'ORD-1', amount: 100 });\n assert.equal(result.validated, true);\n assert.equal(result.paymentStatus, 'CHARGED');\n});\n`;
223
+ fs.writeFileSync(testPath, testCode);
224
+ filesCreated.push(testPath);
225
+ }
226
+ return { filesCreated };
227
+ }
228
+ /**
229
+ * Scaffolds a new typed workflow file and test.
230
+ */
231
+ function generateWorkflow(name, targetDir = process.cwd()) {
232
+ const srcDir = path.join(targetDir, "src", "workflows");
233
+ fs.mkdirSync(srcDir, { recursive: true });
234
+ const kebabName = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
235
+ const pascalName = kebabName.split("-").map(s => s.charAt(0).toUpperCase() + s.slice(1)).join("");
236
+ const camelName = pascalName.charAt(0).toLowerCase() + pascalName.slice(1);
237
+ const filePath = path.join(srcDir, `${kebabName}.workflow.ts`);
238
+ const testPath = path.join(srcDir, `${kebabName}.workflow.test.ts`);
239
+ const workflowContent = `import { Step, flow } from '@siglo/core';\n\nexport interface ${pascalName}Input {\n id: string;\n}\n\nexport interface ${pascalName}Output {\n id: string;\n status: string;\n}\n\nexport const step1 = Step.create("validate", async (param: ${pascalName}Input) => {\n if (!param.id) throw new Error("Missing required field: id");\n return { validated: true };\n});\n\nexport const step2 = Step.create("process", async (param: ${pascalName}Input & { validated: boolean }) => {\n return { status: "COMPLETED" };\n});\n\nexport const ${camelName}Workflow = flow(step1, step2);\nexport default ${camelName}Workflow;\n`;
240
+ const testContent = `import { expect } from "chai";\nimport { createWorkflowHarness } from "@siglo/testing";\nimport { ${camelName}Workflow } from "./${kebabName}.workflow";\n\ndescribe("${pascalName}Workflow", () => {\n it("executes successfully", async () => {\n const harness = createWorkflowHarness(${camelName}Workflow);\n const result = await harness.run({ id: "test-123" });\n expect(result.status).to.equal("COMPLETED");\n harness.assertStepExecuted("validate");\n harness.assertStepExecuted("process");\n });\n});\n`;
241
+ fs.writeFileSync(filePath, workflowContent, "utf-8");
242
+ fs.writeFileSync(testPath, testContent, "utf-8");
243
+ return { filePath, testPath };
244
+ }
245
+ /**
246
+ * Scaffolds a new typed step file and test.
247
+ */
248
+ function generateStep(name, targetDir = process.cwd(), options = {}) {
249
+ (0, step_templates_1.validateStepOptions)(name, options);
250
+ const srcDir = path.join(targetDir, "src", "steps");
251
+ const kebabName = name.toLowerCase().replace(/[^a-z0-9]+/g, "-");
252
+ const pascalName = kebabName.split("-").map(s => s.charAt(0).toUpperCase() + s.slice(1)).join("");
253
+ const camelName = pascalName.charAt(0).toLowerCase() + pascalName.slice(1);
254
+ const filePath = path.join(srcDir, `${kebabName}.step.ts`);
255
+ const testPath = path.join(srcDir, `${kebabName}.step.test.ts`);
256
+ const stepContent = `import { Step } from '@siglo/core';\n\nexport interface ${pascalName}Input {\n [key: string]: any;\n}\n\nexport interface ${pascalName}Output {\n success: boolean;\n}\n\nexport const ${camelName}Step = Step.create("${kebabName}", async (param: ${pascalName}Input): Promise<${pascalName}Output> => {\n return { success: true };\n});\n\nexport default ${camelName}Step;\n`;
257
+ const testContent = `import { expect } from "chai";\nimport { ${camelName}Step } from "./${kebabName}.step";\n\ndescribe("${pascalName}Step", () => {\n it("executes successfully", async () => {\n const result = await ${camelName}Step.execute({});\n expect(result.success).to.be.true;\n });\n});\n`;
258
+ const template = (0, step_templates_1.ecosystemTemplate)(pascalName, kebabName, options);
259
+ if (fs.existsSync(filePath) || fs.existsSync(testPath))
260
+ throw new Error('Step destination already exists');
261
+ fs.mkdirSync(srcDir, { recursive: true });
262
+ fs.writeFileSync(filePath, template?.source ?? stepContent, { encoding: 'utf-8', flag: 'wx' });
263
+ try {
264
+ fs.writeFileSync(testPath, template?.test ?? testContent, { encoding: 'utf-8', flag: 'wx' });
265
+ }
266
+ catch (error) {
267
+ fs.unlinkSync(filePath);
268
+ throw error;
269
+ }
270
+ return { filePath, testPath };
271
+ }
272
+ /**
273
+ * Exports a workflow graph to Mermaid, Graphviz DOT, or JSON format.
274
+ */
275
+ function exportWorkflow(workflow, options = {}) {
276
+ const format = options.format || "mermaid";
277
+ if (format === "json") {
278
+ return typeof workflow.toJSON === "function"
279
+ ? workflow.toJSON()
280
+ : JSON.stringify(workflow, null, 2);
281
+ }
282
+ if (format === "dot") {
283
+ return typeof workflow.toDot === "function"
284
+ ? workflow.toDot({ direction: options.direction })
285
+ : "";
286
+ }
287
+ // Default: mermaid
288
+ return typeof workflow.toMermaid === "function"
289
+ ? workflow.toMermaid({ direction: options.direction, includeBadges: options.includeBadges })
290
+ : toMermaid((0, core_1.inspectGraph)(workflow));
291
+ }
292
+ /**
293
+ * Starts the live workflow monitoring dev server and web dashboard.
294
+ */
295
+ async function startMonitor(options = {}) {
296
+ const { createMonitorServer } = await Promise.resolve().then(() => __importStar(require("@siglo/monitor")));
297
+ return createMonitorServer({
298
+ port: options.port,
299
+ host: options.host,
300
+ namespaceFilter: options.namespace,
301
+ flow: options.flow,
302
+ open: options.open
303
+ });
304
+ }
305
+ /**
306
+ * Reconciles abandoned workflow stacks stuck in RUNNING state past a stale threshold.
307
+ */
308
+ async function reconcileCommand(options = {}) {
309
+ const staleMs = options.staleThreshold ? (0, core_1.parseDuration)(options.staleThreshold) : 10 * 60 * 1000;
310
+ return (0, core_1.reconcileAbandonedStacks)({
311
+ staleThresholdMs: staleMs,
312
+ action: options.action,
313
+ mode: options.mode,
314
+ namespace: options.namespace,
315
+ flowLookup: () => options.flow,
316
+ stacks: options.stacks
317
+ });
318
+ }
319
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ /** Scriptable ecosystem generators. Values are serialized, never interpolated as code. */
2
+ export type GenerateStepOptions = {
3
+ type?: 'generic';
4
+ } | {
5
+ type: 'http';
6
+ url: string;
7
+ } | {
8
+ type: 'crypto';
9
+ provider: 'stripe' | 'github' | 'shopify' | 'slack' | 'svix' | 'generic-hmac';
10
+ } | {
11
+ type: 'ai';
12
+ provider: 'openai' | 'anthropic' | 'gemini' | 'ollama';
13
+ model: string;
14
+ } | {
15
+ type: 'notification';
16
+ channel: 'email' | 'slack' | 'discord' | 'sms' | 'push';
17
+ interactive?: boolean;
18
+ };
19
+ export declare function validateStepOptions(name: string, options: GenerateStepOptions): void;
20
+ export declare function ecosystemTemplate(name: string, file: string, options: GenerateStepOptions): {
21
+ source: string;
22
+ test: string;
23
+ } | undefined;
24
+ //# sourceMappingURL=step-templates.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-templates.d.ts","sourceRoot":"","sources":["../src/step-templates.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,MAAM,MAAM,mBAAmB,GAC3B;IAAE,IAAI,CAAC,EAAE,SAAS,CAAA;CAAE,GACpB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC7B;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,OAAO,GAAG,MAAM,GAAG,cAAc,CAAA;CAAE,GACjG;IAAE,IAAI,EAAE,IAAI,CAAC;IAAC,QAAQ,EAAE,QAAQ,GAAG,WAAW,GAAG,QAAQ,GAAG,QAAQ,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACrF;IAAE,IAAI,EAAE,cAAc,CAAC;IAAC,OAAO,EAAE,OAAO,GAAG,OAAO,GAAG,SAAS,GAAG,KAAK,GAAG,MAAM,CAAC;IAAC,WAAW,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC;AAE7G,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG,IAAI,CAmBpF;AAQD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,mBAAmB,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAAG,SAAS,CAqCxI"}
@@ -0,0 +1,83 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.validateStepOptions = validateStepOptions;
4
+ exports.ecosystemTemplate = ecosystemTemplate;
5
+ function validateStepOptions(name, options) {
6
+ if (!/^[A-Za-z][A-Za-z0-9]*(?:-[A-Za-z0-9]+)*$/.test(name))
7
+ throw new Error('Step name must be a TypeScript identifier or kebab-case name');
8
+ const o = options;
9
+ const keys = { generic: ['type'], http: ['type', 'url'], crypto: ['type', 'provider'], ai: ['type', 'provider', 'model'], notification: ['type', 'channel', 'interactive'] };
10
+ const type = o.type ?? 'generic';
11
+ if (!keys[type])
12
+ throw new Error(`Unsupported step type: ${type}`);
13
+ if (Object.keys(o).some(k => !keys[type].includes(k)))
14
+ throw new Error('Unsupported option for step type');
15
+ if (type === 'http') {
16
+ let url;
17
+ try {
18
+ url = new URL(o.url);
19
+ }
20
+ catch {
21
+ throw new Error('HTTP requires an absolute URL');
22
+ }
23
+ if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.hash)
24
+ throw new Error('HTTP URL must use http(s), without credentials or fragment');
25
+ }
26
+ if (type === 'crypto' && !['stripe', 'github', 'shopify', 'slack', 'svix', 'generic-hmac'].includes(o.provider))
27
+ throw new Error('Unsupported webhook provider');
28
+ if (type === 'ai' && (!['openai', 'anthropic', 'gemini', 'ollama'].includes(o.provider) || typeof o.model !== 'string' || !o.model.trim()))
29
+ throw new Error('AI requires a supported provider and model');
30
+ if (type === 'notification') {
31
+ if (!['email', 'slack', 'discord', 'sms', 'push'].includes(o.channel))
32
+ throw new Error('Unsupported notification channel');
33
+ if (o.interactive !== undefined && typeof o.interactive !== 'boolean')
34
+ throw new Error('interactive must be true or false');
35
+ if (o.interactive && !['email', 'slack'].includes(o.channel))
36
+ throw new Error('Approval supports email or slack');
37
+ }
38
+ }
39
+ const literal = (s) => JSON.stringify(s).replace(/\u2028/g, '\\u2028').replace(/\u2029/g, '\\u2029');
40
+ const schema = `const schema = { '~standard': { version: 1 as const, vendor: 'example', validate(value: unknown) {
41
+ return value && typeof value === 'object' && typeof (value as { id?: unknown }).id === 'string'
42
+ ? { value: value as { id: string } } : { issues: [{ message: 'Expected an object with string id' }] };
43
+ } } };\n`;
44
+ function ecosystemTemplate(name, file, options) {
45
+ const o = options;
46
+ const header = `import test from 'node:test';\nimport assert from 'node:assert/strict';\nimport { create${name}Step } from './${file}.step';\n`;
47
+ if (o.type === 'http') {
48
+ const url = new URL(o.url);
49
+ return {
50
+ source: `import { httpStep } from '@siglo/http';\n\n${schema}\n// Static URLs declare their host automatically. For dynamic URLs, call .allowNetwork([...]).\nexport function create${name}Step() {\n return httpStep(${literal(name)}, { url: ${literal(o.url)}, method: 'POST',\n body: { id: 'example' }, requestSchema: schema, responseSchema: schema });\n}\n`,
51
+ test: header + `import { createMockHttpServer } from '@siglo/http/testing';\nimport { installNetworkInterceptors } from '@siglo/core';\n\ntest('HTTP offline response', async () => {\n installNetworkInterceptors();\n const originalFetch = globalThis.fetch;\n const http = createMockHttpServer();\n try {\n http.get(${literal(url.origin)}).intercept({ path: ${literal(url.pathname + url.search)}, method: 'POST' }).reply(200, { id: 'fixture' });\n const result = await create${name}Step().execute({});\n assert.equal(result.id, 'fixture');\n http.assertDone();\n } finally { http.close(); assert.equal(globalThis.fetch, originalFetch); }\n});\n`
52
+ };
53
+ }
54
+ if (o.type === 'ai')
55
+ return {
56
+ source: `import { aiStep, type AiProviderAdapter } from '@siglo/ai';\n\n${schema}\nexport function create${name}Step(adapter?: AiProviderAdapter) {\n return aiStep(${literal(name)}, { model: { provider: ${literal(o.provider)}, model: ${literal(o.model)}, adapter },\n prompt: 'Return JSON with a string id.', schema,\n jsonSchema: { type: 'object', properties: { id: { type: 'string' } }, required: ['id'], additionalProperties: false } });\n}\n`,
57
+ test: header + `import { MockAiProvider } from '@siglo/ai/testing';\n\ntest('AI offline structured response', async () => {\n const ai = new MockAiProvider([{ text: '{"id":"fixture"}', promptTokens: 10, completionTokens: 5 }]);\n const result = await create${name}Step(ai).execute({});\n assert.deepEqual(result.data, { id: 'fixture' });\n ai.assertDone();\n});\n`
58
+ };
59
+ if (o.type === 'crypto') {
60
+ const sign = {
61
+ stripe: "{ 'stripe-signature': `t=${timestamp},v1=${hmac(`${timestamp}.${body}`)}` }",
62
+ github: "{ 'x-hub-signature-256': `sha256=${hmac(body)}` }",
63
+ shopify: "{ 'x-shopify-hmac-sha256': hmac(body, 'base64') }",
64
+ slack: "{ 'x-slack-request-timestamp': timestamp, 'x-slack-signature': `v0=${hmac(`v0:${timestamp}:${body}`)}` }",
65
+ svix: "{ 'svix-id': 'fixture', 'svix-timestamp': timestamp, 'svix-signature': `v1,${hmac(`fixture.${timestamp}.${body}`, 'base64')}` }",
66
+ 'generic-hmac': "{ 'x-signature': hmac(body) }"
67
+ };
68
+ return {
69
+ source: `import { verifyWebhookStep } from '@siglo/crypto';\n\n// Pass the original raw body, never parsed/re-serialized JSON.\nexport function create${name}Step(secret = () => {\n const value = process.env.WEBHOOK_SECRET;\n if (!value) throw new Error('WEBHOOK_SECRET is required');\n return value;\n}) {\n return verifyWebhookStep(${literal(name)}, { provider: ${literal(o.provider)}, secret,\n payload: (ctx: { rawBody: string | Buffer; headers: Record<string, string> }) => ctx.rawBody,\n signature: ctx => ctx.headers });\n}\n`,
70
+ test: header + `import { createHmac } from 'node:crypto';\n\ntest('valid signature and rejection', async () => {\n const secret = 'synthetic-test-key';\n const body = '{ "id": "fixture" }';\n const timestamp = String(Math.floor(Date.now() / 1000));\n const hmac = (value: string, encoding: 'hex' | 'base64' = 'hex') => createHmac('sha256', secret).update(value).digest(encoding);\n const headers = ${sign[o.provider]};\n const result = await create${name}Step(() => secret).execute({ rawBody: body, headers });\n assert.equal(result.webhookVerified, true);\n await assert.rejects(() => create${name}Step(() => secret).execute({ rawBody: body + 'tampered', headers }));\n});\n`
71
+ };
72
+ }
73
+ if (o.type === 'notification') {
74
+ const recipient = { email: 'fixture@example.test', slack: 'CFIXTURE', discord: 'https://discord.com/api/webhooks/fixture/token', sms: '+15555550123', push: 'fixture-device' }[o.channel];
75
+ const approval = o.interactive;
76
+ return {
77
+ source: `import { ${approval ? 'sendInteractiveApprovalStep' : 'sendNotificationStep'}, type NotificationTransport } from '@siglo/notifications';\n\n// Inject a production transport at the application boundary; see the CLI cookbook.\nexport function create${name}Step(transport: NotificationTransport${approval ? ', callbackBaseUrl: string, signingSecret: string' : ''}) {\n return ${approval ? 'sendInteractiveApprovalStep' : 'sendNotificationStep'}(${literal(name)}, { channel: ${literal(o.channel)}, transport,\n recipient: ${literal(recipient)}, ${approval ? "title: 'Approval requested', correlationKey: 'example-approval', timeout: '1h',\n onApproveEvent: 'approved', onRejectEvent: 'rejected', callbackBaseUrl, signingSecret" : "template: 'Example notification'"} });\n}\n`,
78
+ test: header + `import { MockNotificationTransport } from '@siglo/notifications/testing';\n\ntest('offline ${approval ? 'approval dispatch' : 'delivery'}', async () => {\n const transport = new MockNotificationTransport(${literal(o.channel)});\n const result = await create${name}Step(transport${approval ? ", 'https://example.test/callback', 'synthetic-test-signing-key'" : ''}).execute({});\n assert.equal(result.notificationId, 'mock-1');\n assert.equal(transport.messages.length, 1);\n${approval ? " assert.ok(transport.messages[0].interactiveActions);\n" : ''}});\n`
79
+ };
80
+ }
81
+ return undefined;
82
+ }
83
+ //# sourceMappingURL=step-templates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"step-templates.js","sourceRoot":"","sources":["../src/step-templates.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,58 @@
1
1
  {
2
2
  "name": "@siglo/cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "Developer CLI and workflow visualizer/inspector for Siglo workflows",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./dist/index.d.ts",
10
+ "import": "./dist/index.js",
11
+ "require": "./dist/index.js",
12
+ "default": "./dist/index.js"
13
+ },
14
+ "./package.json": "./package.json"
15
+ },
16
+ "bin": {
17
+ "siglo": "./dist/bin.js"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md",
22
+ "ECOSYSTEM.md",
23
+ "LICENSE"
24
+ ],
25
+ "publishConfig": {
26
+ "access": "public",
27
+ "registry": "https://registry.npmjs.org/"
28
+ },
29
+ "scripts": {
30
+ "build": "tsc -p tsconfig.json",
31
+ "prepublishOnly": "npm run build",
32
+ "test": "npm run build && mocha -r tsx 'src/**/*.test.ts'"
33
+ },
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "git+https://github.com/jsoftgem/siglo.git",
37
+ "directory": "packages/cli"
38
+ },
39
+ "author": "Jerico de Guzman",
40
+ "license": "MIT",
41
+ "bugs": {
42
+ "url": "https://github.com/jsoftgem/siglo/issues"
43
+ },
44
+ "homepage": "https://github.com/jsoftgem/siglo#readme",
45
+ "dependencies": {
46
+ "@siglo/core": "^1.0.0",
47
+ "@siglo/monitor": "^1.0.0"
48
+ },
49
+ "devDependencies": {
50
+ "@types/chai": "^5.2.3",
51
+ "@types/mocha": "^10.0.10",
52
+ "@types/node": "^26.6.5",
53
+ "chai": "^3.5.0",
54
+ "mocha": "^12.0.3",
55
+ "tsx": "^4.23.15",
56
+ "typescript": "~5.7.0"
57
+ }
58
+ }