@agentled/cli 0.6.5 → 0.6.7

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 (50) hide show
  1. package/README.md +25 -0
  2. package/dist/commands/agents.js +7 -2
  3. package/dist/commands/agents.js.map +1 -1
  4. package/dist/commands/auth.js +18 -0
  5. package/dist/commands/auth.js.map +1 -1
  6. package/dist/commands/dryrun.d.ts +23 -0
  7. package/dist/commands/dryrun.js +641 -0
  8. package/dist/commands/dryrun.js.map +1 -0
  9. package/dist/commands/executions.js +67 -0
  10. package/dist/commands/executions.js.map +1 -1
  11. package/dist/commands/fixture.d.ts +10 -0
  12. package/dist/commands/fixture.js +155 -0
  13. package/dist/commands/fixture.js.map +1 -0
  14. package/dist/commands/group-manifest.d.ts +15 -0
  15. package/dist/commands/group-manifest.js +488 -0
  16. package/dist/commands/group-manifest.js.map +1 -0
  17. package/dist/commands/init.d.ts +17 -0
  18. package/dist/commands/init.js +83 -0
  19. package/dist/commands/init.js.map +1 -0
  20. package/dist/commands/onboarding.js +70 -3
  21. package/dist/commands/onboarding.js.map +1 -1
  22. package/dist/commands/test.d.ts +15 -0
  23. package/dist/commands/test.js +98 -0
  24. package/dist/commands/test.js.map +1 -0
  25. package/dist/commands/workflows.js +104 -0
  26. package/dist/commands/workflows.js.map +1 -1
  27. package/dist/commands/workspace.js +65 -0
  28. package/dist/commands/workspace.js.map +1 -1
  29. package/dist/context-schema.js +3 -4
  30. package/dist/context-schema.js.map +1 -1
  31. package/dist/index.js +10 -0
  32. package/dist/index.js.map +1 -1
  33. package/dist/utils/browser-auth.js +6 -2
  34. package/dist/utils/browser-auth.js.map +1 -1
  35. package/dist/utils/pipeline-lint.d.ts +20 -0
  36. package/dist/utils/pipeline-lint.js +348 -0
  37. package/dist/utils/pipeline-lint.js.map +1 -0
  38. package/dist/utils/preflight.js +1 -1
  39. package/dist/utils/test-runner.d.ts +85 -0
  40. package/dist/utils/test-runner.js +283 -0
  41. package/dist/utils/test-runner.js.map +1 -0
  42. package/dist/utils/workspace-folder.d.ts +46 -0
  43. package/dist/utils/workspace-folder.js +340 -0
  44. package/dist/utils/workspace-folder.js.map +1 -0
  45. package/llms-full.txt +13 -0
  46. package/package.json +1 -1
  47. package/patterns/v1/12-event-driven-workflow-groups.md +288 -0
  48. package/scaffolds/extract-threshold-alert.json +3 -3
  49. package/skills/agentled/SKILL.md +102 -26
  50. package/skills/agentled/WHY-AGENTLED.md +15 -0
@@ -0,0 +1,283 @@
1
+ /**
2
+ * Declarative test runner — runs assertions against captured fixture outputs
3
+ * (zero credits) or live API calls (`--live`, costs credits for AI/app steps).
4
+ *
5
+ * Test file format (tests/<workflowId>.test.json):
6
+ * {
7
+ * "workflowId": "wf_abc",
8
+ * "fixtureExecutionId": "exec_xyz",
9
+ * "steps": [
10
+ * {
11
+ * "stepId": "score-lead",
12
+ * "type": "aiAction",
13
+ * "fixtureSource": "exec_xyz/score-lead",
14
+ * "assertions": [
15
+ * { "verb": "hasKey", "path": "score" },
16
+ * { "verb": "isType", "path": "score", "expect": "number" },
17
+ * { "verb": "inRange", "path": "score", "min": 0, "max": 100 },
18
+ * { "verb": "matches", "path": "decision", "pattern": "^(HOT|WARM|COLD)$" }
19
+ * ]
20
+ * }
21
+ * ]
22
+ * }
23
+ *
24
+ * Assertion verbs: hasKey, isType, equals, matches, inRange, hasLength, contains
25
+ */
26
+ import { existsSync, readFileSync } from 'node:fs';
27
+ import { join, resolve } from 'node:path';
28
+ // ---------------------------------------------------------------------------
29
+ // Path accessor
30
+ // ---------------------------------------------------------------------------
31
+ export function getPath(obj, dotPath) {
32
+ if (!dotPath || dotPath === '.')
33
+ return obj;
34
+ const parts = dotPath.split('.');
35
+ let cur = obj;
36
+ for (const part of parts) {
37
+ if (cur === null || cur === undefined)
38
+ return undefined;
39
+ if (Array.isArray(cur)) {
40
+ const idx = parseInt(part, 10);
41
+ cur = isNaN(idx) ? undefined : cur[idx];
42
+ }
43
+ else if (typeof cur === 'object') {
44
+ cur = cur[part];
45
+ }
46
+ else {
47
+ return undefined;
48
+ }
49
+ }
50
+ return cur;
51
+ }
52
+ // ---------------------------------------------------------------------------
53
+ // Assertion runner
54
+ // ---------------------------------------------------------------------------
55
+ export function runAssertion(output, assertion) {
56
+ const value = getPath(output, assertion.path);
57
+ const { verb } = assertion;
58
+ switch (verb) {
59
+ case 'hasKey': {
60
+ const pass = value !== undefined && value !== null;
61
+ return { pass, reason: pass ? '' : `Expected key "${assertion.path}" present and non-null, got: ${JSON.stringify(value)}` };
62
+ }
63
+ case 'isType': {
64
+ const expect = assertion.expect;
65
+ const actual = Array.isArray(value) ? 'array' : typeof value;
66
+ return { pass: actual === expect, reason: `Expected "${assertion.path}" type "${expect}", got "${actual}"` };
67
+ }
68
+ case 'equals': {
69
+ const pass = JSON.stringify(value) === JSON.stringify(assertion.expect);
70
+ return { pass, reason: pass ? '' : `Expected "${assertion.path}" to equal ${JSON.stringify(assertion.expect)}, got ${JSON.stringify(value)}` };
71
+ }
72
+ case 'matches': {
73
+ if (typeof value !== 'string')
74
+ return { pass: false, reason: `Expected "${assertion.path}" string for regex, got ${typeof value}` };
75
+ const re = new RegExp(assertion.pattern ?? '');
76
+ const pass = re.test(value);
77
+ return { pass, reason: pass ? '' : `Expected "${assertion.path}" to match /${assertion.pattern}/, got "${value}"` };
78
+ }
79
+ case 'inRange': {
80
+ if (typeof value !== 'number')
81
+ return { pass: false, reason: `Expected "${assertion.path}" number, got ${typeof value}` };
82
+ const min = assertion.min ?? -Infinity;
83
+ const max = assertion.max ?? Infinity;
84
+ const pass = value >= min && value <= max;
85
+ return { pass, reason: pass ? '' : `Expected "${assertion.path}" between ${min} and ${max}, got ${value}` };
86
+ }
87
+ case 'hasLength': {
88
+ if (!Array.isArray(value) && typeof value !== 'string')
89
+ return { pass: false, reason: `Expected "${assertion.path}" array/string, got ${typeof value}` };
90
+ const len = value.length;
91
+ if (assertion.expect !== undefined) {
92
+ const pass = len === Number(assertion.expect);
93
+ return { pass, reason: pass ? '' : `Expected length ${assertion.expect}, got ${len}` };
94
+ }
95
+ return { pass: len > 0, reason: `Expected non-empty, got length ${len}` };
96
+ }
97
+ case 'contains': {
98
+ if (typeof value === 'string') {
99
+ const pass = value.includes(String(assertion.expect ?? ''));
100
+ return { pass, reason: pass ? '' : `Expected "${assertion.path}" to contain "${assertion.expect}", got "${value}"` };
101
+ }
102
+ if (Array.isArray(value)) {
103
+ const pass = value.some((item) => JSON.stringify(item) === JSON.stringify(assertion.expect));
104
+ return { pass, reason: pass ? '' : `Expected array to contain ${JSON.stringify(assertion.expect)}` };
105
+ }
106
+ return { pass: false, reason: `Expected "${assertion.path}" string/array for contains` };
107
+ }
108
+ default:
109
+ return { pass: false, reason: `Unknown assertion verb: "${verb}"` };
110
+ }
111
+ }
112
+ // ---------------------------------------------------------------------------
113
+ // Fixture loader
114
+ // ---------------------------------------------------------------------------
115
+ export function loadFixture(wsDir, fixtureSource) {
116
+ const parts = fixtureSource.split('/');
117
+ if (parts.length < 2)
118
+ return null;
119
+ const [executionId, ...stepParts] = parts;
120
+ const stepId = stepParts.join('/');
121
+ const candidates = [];
122
+ if (wsDir)
123
+ candidates.push(join(wsDir, 'fixtures', 'step-outputs', executionId, `${stepId}.json`));
124
+ candidates.push(resolve('fixtures', 'step-outputs', executionId, `${stepId}.json`));
125
+ for (const candidate of candidates) {
126
+ if (existsSync(candidate)) {
127
+ try {
128
+ return JSON.parse(readFileSync(candidate, 'utf-8'));
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ }
135
+ return null;
136
+ }
137
+ // ---------------------------------------------------------------------------
138
+ // Run a step in fixture mode (zero credits)
139
+ // ---------------------------------------------------------------------------
140
+ export function runStepFixture(step, wsDir) {
141
+ const result = { stepId: step.stepId, description: step.description, passed: 0, failed: 0, skipped: 0, errors: [], mode: 'fixture' };
142
+ if (!step.fixtureSource) {
143
+ result.mode = 'skipped';
144
+ result.skipped = step.assertions.length;
145
+ result.errors.push('No fixtureSource set — run `agentled fixture capture` first.');
146
+ return result;
147
+ }
148
+ const fixture = loadFixture(wsDir, step.fixtureSource);
149
+ if (!fixture) {
150
+ result.mode = 'skipped';
151
+ result.skipped = step.assertions.length;
152
+ result.errors.push(`Fixture not found: ${step.fixtureSource}`);
153
+ return result;
154
+ }
155
+ const output = fixture.output ?? fixture;
156
+ for (const assertion of step.assertions) {
157
+ if (assertion.path === '?') {
158
+ result.skipped++;
159
+ continue;
160
+ }
161
+ const { pass, reason } = runAssertion(output, assertion);
162
+ if (pass)
163
+ result.passed++;
164
+ else {
165
+ result.failed++;
166
+ result.errors.push(reason);
167
+ }
168
+ }
169
+ return result;
170
+ }
171
+ export async function runStepLive(step, client) {
172
+ const result = { stepId: step.stepId, description: step.description, passed: 0, failed: 0, skipped: 0, errors: [], mode: 'live' };
173
+ let output;
174
+ try {
175
+ if (step.type === 'code') {
176
+ const response = await client.testCodeAction(step.codeConfig?.code ?? '', step.codeConfig?.language ?? 'javascript', step.liveInputs ?? {});
177
+ output = response.output ?? response.result ?? response;
178
+ }
179
+ else if (step.type === 'aiAction' || step.type === 'aiActionWithTools') {
180
+ if (!step.promptTemplate) {
181
+ result.mode = 'skipped';
182
+ result.skipped = step.assertions.length;
183
+ result.errors.push('Live mode requires "promptTemplate".');
184
+ return result;
185
+ }
186
+ const response = await client.testAiAction(step.promptTemplate, step.promptVariables ?? step.liveInputs ?? {}, step.promptResponseStructure ?? {});
187
+ output = response.output ?? response.result ?? response;
188
+ }
189
+ else if (step.type === 'appAction') {
190
+ if (!step.appId || !step.actionId) {
191
+ result.mode = 'skipped';
192
+ result.skipped = step.assertions.length;
193
+ result.errors.push('Live mode requires "appId" and "actionId".');
194
+ return result;
195
+ }
196
+ const response = await client.testAppAction(step.appId, step.actionId, step.appInputs ?? step.liveInputs ?? {});
197
+ output = response.output ?? response.result ?? response;
198
+ }
199
+ else {
200
+ result.mode = 'skipped';
201
+ result.skipped = step.assertions.length;
202
+ result.errors.push(`Step type "${step.type}" doesn't support live testing.`);
203
+ return result;
204
+ }
205
+ }
206
+ catch (err) {
207
+ result.failed = step.assertions.length;
208
+ result.errors.push(`API call failed: ${err instanceof Error ? err.message : String(err)}`);
209
+ return result;
210
+ }
211
+ for (const assertion of step.assertions) {
212
+ if (assertion.path === '?') {
213
+ result.skipped++;
214
+ continue;
215
+ }
216
+ const { pass, reason } = runAssertion(output, assertion);
217
+ if (pass)
218
+ result.passed++;
219
+ else {
220
+ result.failed++;
221
+ result.errors.push(reason);
222
+ }
223
+ }
224
+ return result;
225
+ }
226
+ export function makeTestSkeleton(workflowId, pipeline) {
227
+ const allSteps = (Array.isArray(pipeline.steps) ? pipeline.steps : []);
228
+ const testable = allSteps.filter((s) => ['aiAction', 'aiActionWithTools', 'appAction', 'code'].includes(String(s.type ?? '')));
229
+ return {
230
+ workflowId,
231
+ workflowName: String(pipeline.name ?? workflowId),
232
+ description: `Auto-generated test skeleton for ${pipeline.name ?? workflowId}. Edit assertions to match expected outputs.`,
233
+ fixtureExecutionId: null,
234
+ steps: testable.map((s) => {
235
+ const stepId = String(s.id ?? '');
236
+ const type = String(s.type ?? '');
237
+ const app = s.app;
238
+ const test = {
239
+ stepId,
240
+ type,
241
+ description: String(s.name ?? stepId),
242
+ fixtureSource: null,
243
+ assertions: [],
244
+ };
245
+ if (type === 'aiAction' || type === 'aiActionWithTools') {
246
+ const responseStructure = s.pipelineStepPrompt?.responseStructure;
247
+ if (responseStructure && typeof responseStructure === 'object') {
248
+ test.assertions = Object.keys(responseStructure).slice(0, 5).map((key) => ({
249
+ verb: 'hasKey',
250
+ path: key,
251
+ comment: `Step should output a "${key}" field`,
252
+ }));
253
+ }
254
+ else {
255
+ test.assertions = [{ verb: 'hasKey', path: '?', comment: 'Replace ? with an expected output field' }];
256
+ }
257
+ }
258
+ else if (type === 'appAction') {
259
+ const actionId = String(app?.actionId ?? '');
260
+ if (actionId.includes('read-list')) {
261
+ test.assertions = [
262
+ { verb: 'hasKey', path: 'listEntries' },
263
+ { verb: 'isType', path: 'listEntries', expect: 'array' },
264
+ ];
265
+ }
266
+ else if (actionId.includes('find-email')) {
267
+ test.assertions = [
268
+ { verb: 'hasKey', path: 'email' },
269
+ { verb: 'matches', path: 'email', pattern: '.+@.+\\..+' },
270
+ ];
271
+ }
272
+ else {
273
+ test.assertions = [{ verb: 'hasKey', path: '?', comment: 'Replace ? with an expected output field' }];
274
+ }
275
+ }
276
+ else if (type === 'code') {
277
+ test.assertions = [{ verb: 'hasKey', path: '?', comment: 'Replace ? with an expected output field' }];
278
+ }
279
+ return test;
280
+ }),
281
+ };
282
+ }
283
+ //# sourceMappingURL=test-runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"test-runner.js","sourceRoot":"","sources":["../../src/utils/test-runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Workspace folder helpers — local agentled_<slug>/ directory used as the
3
+ * agent's working tree for building, testing, and iterating on workflows.
4
+ *
5
+ * Folder layout:
6
+ *
7
+ * agentled_<slug>/
8
+ * ├── README.md # agent-facing guide
9
+ * ├── .agentled/
10
+ * │ ├── workspace.json # workspaceId, slug, apiBase, syncedAt
11
+ * │ └── cache/
12
+ * │ ├── apps.json # app registry
13
+ * │ └── models.json # supported models
14
+ * ├── docs/
15
+ * │ ├── SKILL.md # full skill reference (copied from package)
16
+ * │ └── GOTCHAS.md # documented failure modes
17
+ * ├── examples/
18
+ * │ ├── scaffolds/ # bundled scaffold JSONs (editable)
19
+ * │ └── live/ # workflows pulled from the workspace
20
+ * ├── fixtures/
21
+ * │ └── step-outputs/ # captured step outputs (zero-credit replay)
22
+ * ├── tests/ # <wfId>.test.json declarative test files
23
+ * └── drafts/ # in-progress pipeline JSON files
24
+ */
25
+ export interface WorkspaceMeta {
26
+ workspaceId: string;
27
+ slug: string;
28
+ name: string;
29
+ apiBase: string;
30
+ syncedAt: string;
31
+ }
32
+ export declare function findWorkspaceDir(cwd?: string): string | null;
33
+ export declare function readWorkspaceMeta(wsDir: string): WorkspaceMeta;
34
+ export declare function writeWorkspaceMeta(wsDir: string, meta: WorkspaceMeta): void;
35
+ export declare function bundledScaffoldsDir(): string;
36
+ export declare function bundledSkillMd(): string;
37
+ export declare const GOTCHAS_MD = "# Agentled \u2014 Documented Failure Modes (GOTCHAS)\n\nThese pass JSON syntax validation but silently misbehave at runtime.\nRun `agentled workflows lint <file>` to catch them statically before deploying.\n\n---\n\n## 1. `criteria` not `conditions` in entryConditions [CRITERIA_NOT_CONDITIONS]\n\n**Wrong:** `{ \"entryConditions\": { \"conditions\": [...] } }`\n**Correct:** `{ \"entryConditions\": { \"criteria\": [...] } }`\n\nThe executor reads `entryConditions.criteria`. The key `conditions` is silently ignored.\n\n---\n\n## 2. `variable` not `field` in criteria items [VARIABLE_NOT_FIELD]\n\n**Wrong:** `{ \"field\": \"{{steps.x.score}}\", \"operator\": \">\", \"value\": 70 }`\n**Correct:** `{ \"variable\": \"{{steps.x.score}}\", \"operator\": \">\", \"value\": 70 }`\n\nUsing `field` causes the criterion to be silently skipped.\n\n---\n\n## 3. Gmail label_id must be the internal Label_XXXX ID [GMAIL_LABEL_DISPLAY_NAME]\n\nGmail's API requires `Label_XXXXXXXXXX` IDs, not display names.\nAdd a `GMAIL_CREATE_LABEL` step before and use `{{steps.ensure-label.id}}`.\n\n---\n\n## 4. `aiActionWithTools` with no tools [AI_STEP_TOOLS_REQUIRED]\n\nA step with `type: \"aiActionWithTools\"` must have at least one tool in\n`step.tools` or `step.agent.tools`.\n\nValid `builtinType` values: `web_search`, `file_search`, `code_interpreter`,\n`fetch_website_content`, `kg_search`, `kg_traverse`, `kg_nodes`, `kg_write`,\n`workspace_memory`.\n\n---\n\n## 5. Email steps need type + approval action + outreachProfile [EMAIL_MISSING_*]\n\nThree required pieces:\n- `pipelineStepPrompt.type: \"email\"`\n- `onApproval.action: \"schedule-email\"`\n- `outreachProfile` input page in `context.inputPages`\n\nMissing the schedule-email action means the email is drafted but never sent.\n\n---\n\n## 6. Only the first step in a loop gets `loopConfig` [LOOP_CONFIG_MULTIPLE_STEPS]\n\n`loopConfig` must be on the first step in the loop chain only. Subsequent\nsteps inside the loop iterate automatically.\n\n---\n\n## 7. Don't pass raw `{{input.*}}` directly to search APIs [RAW_INPUT_TO_SEARCH]\n\nAdd an aiAction step before the search that generates optimized queries.\nRaw user input makes poor search queries.\n\n---\n\n## 8. Child workflows must use `return` step, not `milestone` [CHILD_WORKFLOW_NO_RETURN]\n\nIf a workflow is called via `agentled.call-workflow`, use `type: \"return\"`.\n`milestone` produces no return data. Also set `context.executionInputConfig.internal: true`.\n\n---\n\n## 9. Model IDs are internal format, not Anthropic format [MODEL_ID_FORMAT]\n\nWrong: `claude-sonnet-4-6`. Correct: `claude-4-6-sonnet`.\nRun `agentled models list` for valid internal IDs.\n\n---\n\n## 10. Native app actionId must include appId prefix [ACTION_ID_MISSING_PREFIX]\n\nWrong: `{ \"id\": \"kg\", \"actionId\": \"read-list\" }`\nCorrect: `{ \"id\": \"kg\", \"actionId\": \"kg.read-list\" }`\n\n---\n\n## 11. `loop_completion` criteria requires `onCriteriaFail: \"wait\"` [LOOP_COMPLETION_NOT_WAIT]\n\nWithout `onCriteriaFail: \"wait\"`, the step skips instead of blocking until\nthe loop finishes. The `stepId` field is also required.\n\n---\n\n## 12. Arrays in JSON template strings \u2014 don't JSON.stringify\n\nThe serializer detects when a template variable is the sole content of a JSON\nfield and inlines the raw value. Pass `{ \"items\": \"{{steps.x.items}}\" }`\ndirectly \u2014 no stringify needed.\n\n---\n\n## 13. `kg.upsert-rows` needs `userKey` for dedup; `kg.add-rows` always inserts\n\n`kg.upsert-rows` with `userKey`: same key = same row, cross-run dedup O(1).\n`kg.add-rows`: always inserts a new row, duplicates accumulate.\nUse `mergeStrategy: \"merge\"` to preserve downstream-added fields.\n";
38
+ export declare function makeWorkspaceReadme(meta: WorkspaceMeta): string;
39
+ export declare function createWorkspaceFolder(folderPath: string, meta: WorkspaceMeta, opts?: {
40
+ appsList?: unknown;
41
+ modelsList?: unknown;
42
+ }): void;
43
+ export declare function refreshWorkspaceFolder(wsDir: string, opts: {
44
+ appsList?: unknown;
45
+ modelsList?: unknown;
46
+ }): void;