@agentled/cli 0.1.5 → 0.4.3

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 (43) hide show
  1. package/README.md +136 -0
  2. package/dist/commands/auth.js +30 -0
  3. package/dist/commands/auth.js.map +1 -1
  4. package/dist/commands/examples.d.ts +15 -0
  5. package/dist/commands/examples.js +100 -0
  6. package/dist/commands/examples.js.map +1 -0
  7. package/dist/commands/scaffold.d.ts +14 -0
  8. package/dist/commands/scaffold.js +103 -0
  9. package/dist/commands/scaffold.js.map +1 -0
  10. package/dist/commands/schema.d.ts +10 -0
  11. package/dist/commands/schema.js +58 -0
  12. package/dist/commands/schema.js.map +1 -0
  13. package/dist/commands/skills.d.ts +9 -0
  14. package/dist/commands/skills.js +94 -0
  15. package/dist/commands/skills.js.map +1 -0
  16. package/dist/commands/workflows.js +227 -9
  17. package/dist/commands/workflows.js.map +1 -1
  18. package/dist/index.js +6 -0
  19. package/dist/index.js.map +1 -1
  20. package/dist/utils/preflight.d.ts +25 -0
  21. package/dist/utils/preflight.js +185 -0
  22. package/dist/utils/preflight.js.map +1 -0
  23. package/dist/utils/skills.d.ts +49 -0
  24. package/dist/utils/skills.js +214 -0
  25. package/dist/utils/skills.js.map +1 -0
  26. package/package.json +4 -1
  27. package/patterns/v1/00-why-agentic-ops.md +107 -0
  28. package/patterns/v1/01-trigger-design.md +107 -0
  29. package/patterns/v1/02-dedup-gates.md +135 -0
  30. package/patterns/v1/03-credit-efficiency.md +130 -0
  31. package/patterns/v1/04-loop-patterns.md +147 -0
  32. package/patterns/v1/05-child-workflow-contracts.md +151 -0
  33. package/patterns/v1/06-conditional-routing.md +151 -0
  34. package/patterns/v1/07-error-handling.md +157 -0
  35. package/patterns/v1/08-composed-email-approval.md +130 -0
  36. package/patterns/v1/09-reports-and-knowledge-storage.md +166 -0
  37. package/scaffolds/README.md +61 -0
  38. package/scaffolds/email-polling-dedup.json +71 -0
  39. package/scaffolds/extract-threshold-alert.json +131 -0
  40. package/scaffolds/lead-scoring-kg.json +84 -0
  41. package/scaffolds/list-match-email.json +131 -0
  42. package/scaffolds/minimal.json +20 -0
  43. package/skills/agentled/SKILL.md +568 -0
@@ -0,0 +1,185 @@
1
+ /**
2
+ * Client-side preflight checks for a pipeline JSON before it's sent to the
3
+ * server. Catches the "Nick-class" failure mode (invalid step types, missing
4
+ * required fields, unreachable steps, silently-stripped root fields) without
5
+ * spending a create + validate + delete round trip.
6
+ *
7
+ * The valid step types list is kept in sync with the orchestrator's runtime
8
+ * VALID_STEP_TYPES via the drift test in
9
+ * agentled-mcp-server/__tests__/skill-step-types.test.ts.
10
+ */
11
+ /**
12
+ * Canonical valid step types. Must stay in sync with:
13
+ * shared/services/chat/orchestrator/validators/index.ts (runtime)
14
+ * packages/cli/skills/agentled/SKILL.md (agent-facing doc)
15
+ * agentled-mcp-server/__tests__/skill-step-types.test.ts (drift guard)
16
+ */
17
+ const VALID_STEP_TYPES = new Set([
18
+ 'trigger', 'appAction', 'aiAction', 'aiActionWithTools', 'toolAction',
19
+ 'code', 'knowledgeSync', 'return', 'milestone', 'share', 'wait',
20
+ 'branch', 'parallel', 'loop', 'end_if', 'agentOrchestrator',
21
+ 'manualAction', 'systemAction',
22
+ ]);
23
+ /**
24
+ * Root-level fields that the API silently strips. Detecting these at the
25
+ * step root is the single highest-leverage check — it's the exact class of
26
+ * bug that produced Nick's 201-created-but-broken workflows.
27
+ */
28
+ const STRIPPED_ROOT_FIELDS = {
29
+ prompt: 'Move to `pipelineStepPrompt.template`',
30
+ responseStructure: 'Move to `pipelineStepPrompt.responseStructure`',
31
+ appId: 'Move into `app: { id, actionId, source: "native" }`',
32
+ actionId: 'Move into `app: { id, actionId, source: "native" }`',
33
+ listKey: 'Use `knowledgeSync.listKey` (for knowledgeSync steps) or put inside `stepInputData`',
34
+ channel: 'Put inside `stepInputData.channel`',
35
+ webhookUrl: 'Put inside `stepInputData.webhookUrl`',
36
+ condition: 'Use `entryConditions.criteria[]` with { variable, operator, value }',
37
+ triggerType: 'Use `pipelineStepStartConditions.trigger.type` instead — `triggerType` at step root is silently stripped',
38
+ };
39
+ /** Steps where we expect an outgoing `next` link (everything except terminals). */
40
+ const TERMINAL_TYPES = new Set(['milestone', 'return', 'end_if']);
41
+ export function preflightPipeline(pipeline) {
42
+ const errors = [];
43
+ const warnings = [];
44
+ if (!pipeline || typeof pipeline !== 'object') {
45
+ errors.push({ severity: 'error', code: 'not-object', message: 'Pipeline is not a JSON object' });
46
+ return { valid: false, errors, warnings, stepCount: 0 };
47
+ }
48
+ if (typeof pipeline.name !== 'string' || pipeline.name.trim() === '') {
49
+ errors.push({ severity: 'error', code: 'missing-name', message: 'Top-level `name` is required' });
50
+ }
51
+ const steps = pipeline.steps;
52
+ if (!Array.isArray(steps) || steps.length === 0) {
53
+ errors.push({ severity: 'error', code: 'missing-steps', message: 'Top-level `steps` must be a non-empty array' });
54
+ return { valid: errors.length === 0, errors, warnings, stepCount: 0 };
55
+ }
56
+ const stepIds = new Set();
57
+ for (const step of steps) {
58
+ if (!step || typeof step !== 'object') {
59
+ errors.push({ severity: 'error', code: 'bad-step', message: 'Step is not an object' });
60
+ continue;
61
+ }
62
+ if (typeof step.id !== 'string' || step.id.trim() === '') {
63
+ errors.push({ severity: 'error', code: 'missing-id', message: 'Step is missing `id`' });
64
+ }
65
+ else if (stepIds.has(step.id)) {
66
+ errors.push({ severity: 'error', stepId: step.id, code: 'duplicate-id', message: `Duplicate step id: ${step.id}` });
67
+ }
68
+ else {
69
+ stepIds.add(step.id);
70
+ }
71
+ // type check — the Nick-class bug
72
+ if (typeof step.type !== 'string') {
73
+ errors.push({ severity: 'error', stepId: step.id, code: 'missing-type', message: 'Step is missing `type`' });
74
+ }
75
+ else if (!VALID_STEP_TYPES.has(step.type)) {
76
+ errors.push({
77
+ severity: 'error',
78
+ stepId: step.id,
79
+ code: 'invalid-type',
80
+ message: `Unknown step type "${step.type}". Valid: ${[...VALID_STEP_TYPES].sort().join(', ')}`,
81
+ suggestedFix: suggestTypeFix(step.type),
82
+ });
83
+ }
84
+ // silently-stripped root fields
85
+ for (const [field, fix] of Object.entries(STRIPPED_ROOT_FIELDS)) {
86
+ if (Object.prototype.hasOwnProperty.call(step, field)) {
87
+ warnings.push({
88
+ severity: 'warning',
89
+ stepId: step.id,
90
+ code: 'stripped-root-field',
91
+ message: `Field \`${field}\` at step root will be silently stripped on save`,
92
+ suggestedFix: fix,
93
+ });
94
+ }
95
+ }
96
+ // aiAction + aiActionWithTools must have pipelineStepPrompt.template
97
+ if ((step.type === 'aiAction' || step.type === 'aiActionWithTools')) {
98
+ const tpl = step.pipelineStepPrompt?.template;
99
+ if (typeof tpl !== 'string' || tpl.trim() === '') {
100
+ errors.push({
101
+ severity: 'error',
102
+ stepId: step.id,
103
+ code: 'missing-prompt-template',
104
+ message: `${step.type} step requires \`pipelineStepPrompt.template\``,
105
+ });
106
+ }
107
+ }
108
+ // appAction must have app.id + app.actionId
109
+ if (step.type === 'appAction') {
110
+ if (!step.app || typeof step.app !== 'object') {
111
+ errors.push({
112
+ severity: 'error', stepId: step.id, code: 'missing-app',
113
+ message: 'appAction step requires `app: { id, actionId, source }`',
114
+ });
115
+ }
116
+ else {
117
+ if (typeof step.app.id !== 'string') {
118
+ errors.push({ severity: 'error', stepId: step.id, code: 'missing-app-id', message: '`app.id` is required on appAction steps' });
119
+ }
120
+ if (typeof step.app.actionId !== 'string') {
121
+ errors.push({ severity: 'error', stepId: step.id, code: 'missing-action-id', message: '`app.actionId` is required on appAction steps' });
122
+ }
123
+ }
124
+ }
125
+ // trigger steps need pipelineStepStartConditions.trigger.type
126
+ // (the runtime reads this; `triggerType` at step root is not in the
127
+ // step schema and is silently stripped on save)
128
+ if (step.type === 'trigger') {
129
+ const tType = step.pipelineStepStartConditions?.trigger?.type;
130
+ if (typeof tType !== 'string') {
131
+ errors.push({
132
+ severity: 'error', stepId: step.id, code: 'missing-trigger-type',
133
+ message: 'trigger step requires `pipelineStepStartConditions.trigger.type` (manual | schedule | webhook | event | delay | app_event)',
134
+ suggestedFix: 'Set `pipelineStepStartConditions: { trigger: { type: "manual" } }` (or replace "manual" with schedule/webhook/event/delay/app_event).',
135
+ });
136
+ }
137
+ }
138
+ // non-terminal steps should have a next.stepId
139
+ if (!TERMINAL_TYPES.has(step.type)) {
140
+ const nextId = step.next?.stepId;
141
+ if (typeof step.type === 'string' && VALID_STEP_TYPES.has(step.type) && !nextId) {
142
+ warnings.push({
143
+ severity: 'warning', stepId: step.id, code: 'missing-next',
144
+ message: `Non-terminal step "${step.id}" has no \`next.stepId\` — will halt after this step`,
145
+ });
146
+ }
147
+ }
148
+ }
149
+ // next.stepId must point to an existing step
150
+ for (const step of steps) {
151
+ if (!step?.next?.stepId)
152
+ continue;
153
+ if (!stepIds.has(step.next.stepId)) {
154
+ errors.push({
155
+ severity: 'error', stepId: step.id, code: 'dangling-next',
156
+ message: `Step "${step.id}" next.stepId "${step.next.stepId}" does not reference any step`,
157
+ });
158
+ }
159
+ }
160
+ return { valid: errors.length === 0, errors, warnings, stepCount: steps.length };
161
+ }
162
+ /**
163
+ * Heuristic fix suggestions for the exact invented types Nick-class agents produce.
164
+ */
165
+ function suggestTypeFix(invalid) {
166
+ const map = {
167
+ ai: 'Use `type: "aiAction"` (or `aiActionWithTools` if the LLM needs runtime tools).',
168
+ integration: 'Use `type: "appAction"` with `app: { id, actionId, source: "native" }`.',
169
+ conditional_integration: 'Use `type: "appAction"` with `entryConditions.criteria`.',
170
+ knowledge_graph_query: 'Use `type: "appAction"` with `app.id: "kg"`, actionId one of `read-list`/`read-text`/`get-rows-by-ids`/`traverse-edges`.',
171
+ knowledge_graph_upsert: 'Use `type: "appAction"` with `app.id: "kg"`, actionId `add-rows`/`update-rows`/`upsert-text`.',
172
+ knowledge_graph: 'Use `type: "appAction"` with `app.id: "kg"` (see `agentled apps actions kg`).',
173
+ slack: 'Use `type: "appAction"` with `app.id: "slack"` (or a `webhook` appAction if using a Slack incoming webhook URL).',
174
+ gmail: 'Use `type: "appAction"` with `app.id: "gmail"`.',
175
+ webhook: '`webhook` is a `triggerType` on a `trigger` step, not a step type. For outbound webhooks use `app.id: "webhook"` with actionId `trigger`.',
176
+ schedule: '`schedule` is a `triggerType` on a `trigger` step, not a step type.',
177
+ };
178
+ return map[invalid];
179
+ }
180
+ export function formatPreflightIssue(issue) {
181
+ const scope = issue.stepId ? `[${issue.stepId}] ` : '';
182
+ const fix = issue.suggestedFix ? `\n fix: ${issue.suggestedFix}` : '';
183
+ return ` - ${scope}${issue.message} (${issue.code})${fix}`;
184
+ }
185
+ //# sourceMappingURL=preflight.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"preflight.js","sourceRoot":"","sources":["../../src/utils/preflight.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Skills installer — copies the bundled Agentled Claude Code skills into the
3
+ * user's `~/.claude/skills/` (global) or `./.claude/skills/` (project) dir.
4
+ *
5
+ * Why: When an agent drives the CLI with a fresh Claude Code session, it does
6
+ * not have the Agentled skill loaded unless the skill is present on disk in a
7
+ * Claude-discoverable location. Without the skill, the LLM invents invalid
8
+ * step types (`type: "ai"`, `knowledge_graph_query`, …) — the exact class of
9
+ * silent CLI failure that MCP-025 is closing.
10
+ *
11
+ * The installer is version-aware:
12
+ * - Reads a `version:` frontmatter field from each `SKILL.md`
13
+ * - Leaves newer or hand-edited skills alone (unless --force)
14
+ * - Reports status so we can print a one-line summary after `auth login`
15
+ */
16
+ export type SkillInstallOutcome = 'installed' | 'updated' | 'up-to-date' | 'newer-local' | 'hand-edited' | 'forced';
17
+ export interface SkillInstallResult {
18
+ skill: string;
19
+ outcome: SkillInstallOutcome;
20
+ bundledVersion: string;
21
+ installedVersion: string | null;
22
+ targetPath: string;
23
+ }
24
+ export interface InstallSkillsOptions {
25
+ /** true = install to `~/.claude/skills/` (global); false = `./.claude/skills/` (project) */
26
+ global?: boolean;
27
+ /** overwrite regardless of version comparison or local edits */
28
+ force?: boolean;
29
+ }
30
+ /**
31
+ * Locate the `skills/` directory that ships with @agentled/cli.
32
+ *
33
+ * When running from source (`node dist/index.js`) the layout is:
34
+ * packages/cli/dist/utils/skills.js → packages/cli/skills/…
35
+ * When installed globally via npm, the package layout is the same relative
36
+ * structure (`dist/utils/skills.js` → `skills/`).
37
+ */
38
+ export declare function resolveBundledSkillsDir(): string;
39
+ export declare function getSkillsTargetDir(global: boolean): string;
40
+ export declare function installSkills(options?: InstallSkillsOptions): SkillInstallResult[];
41
+ export declare function describeSkillsInstall(results: SkillInstallResult[], targetDir: string): string;
42
+ /**
43
+ * Produce a short one-line hint for the `auth login` summary, e.g.
44
+ * "Skill installed: agentled v0.2.0 → ~/.claude/skills/"
45
+ * "Skill already installed (v0.1.0), latest is v0.2.0 — run `agentled skills update` to refresh."
46
+ *
47
+ * Returns null if there is nothing worth showing.
48
+ */
49
+ export declare function summarizeForLoginBanner(results: SkillInstallResult[], targetDir: string): string | null;
@@ -0,0 +1,214 @@
1
+ /**
2
+ * Skills installer — copies the bundled Agentled Claude Code skills into the
3
+ * user's `~/.claude/skills/` (global) or `./.claude/skills/` (project) dir.
4
+ *
5
+ * Why: When an agent drives the CLI with a fresh Claude Code session, it does
6
+ * not have the Agentled skill loaded unless the skill is present on disk in a
7
+ * Claude-discoverable location. Without the skill, the LLM invents invalid
8
+ * step types (`type: "ai"`, `knowledge_graph_query`, …) — the exact class of
9
+ * silent CLI failure that MCP-025 is closing.
10
+ *
11
+ * The installer is version-aware:
12
+ * - Reads a `version:` frontmatter field from each `SKILL.md`
13
+ * - Leaves newer or hand-edited skills alone (unless --force)
14
+ * - Reports status so we can print a one-line summary after `auth login`
15
+ */
16
+ import { existsSync, readFileSync, mkdirSync, readdirSync, statSync, cpSync } from 'node:fs';
17
+ import { join, dirname, resolve } from 'node:path';
18
+ import { fileURLToPath } from 'node:url';
19
+ import { homedir } from 'node:os';
20
+ /**
21
+ * Locate the `skills/` directory that ships with @agentled/cli.
22
+ *
23
+ * When running from source (`node dist/index.js`) the layout is:
24
+ * packages/cli/dist/utils/skills.js → packages/cli/skills/…
25
+ * When installed globally via npm, the package layout is the same relative
26
+ * structure (`dist/utils/skills.js` → `skills/`).
27
+ */
28
+ export function resolveBundledSkillsDir() {
29
+ const here = fileURLToPath(import.meta.url);
30
+ // dist/utils/skills.js → package root is two levels up
31
+ const pkgRoot = resolve(dirname(here), '..', '..');
32
+ return join(pkgRoot, 'skills');
33
+ }
34
+ export function getSkillsTargetDir(global) {
35
+ return global
36
+ ? join(homedir(), '.claude', 'skills')
37
+ : join(process.cwd(), '.claude', 'skills');
38
+ }
39
+ /**
40
+ * Parse a `version:` field out of the YAML-style frontmatter at the top of a
41
+ * SKILL.md file. Returns null if no frontmatter or no version field is present.
42
+ */
43
+ function parseSkillVersion(skillMdPath) {
44
+ try {
45
+ const content = readFileSync(skillMdPath, 'utf-8');
46
+ // Only inspect frontmatter (between the first two --- delimiters)
47
+ const fmMatch = content.match(/^---\n([\s\S]*?)\n---/);
48
+ if (!fmMatch)
49
+ return null;
50
+ const versionMatch = fmMatch[1].match(/^version:\s*(.+)$/m);
51
+ return versionMatch ? versionMatch[1].trim() : null;
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ /**
58
+ * Compare two semver-ish version strings. Returns -1, 0, or 1.
59
+ * Handles missing prereleases by treating undefined segments as 0.
60
+ */
61
+ function compareVersions(a, b) {
62
+ const parse = (v) => v.replace(/^v/, '').split('.').map(n => parseInt(n, 10) || 0);
63
+ const [a1, a2 = 0, a3 = 0] = parse(a);
64
+ const [b1, b2 = 0, b3 = 0] = parse(b);
65
+ if (a1 !== b1)
66
+ return a1 < b1 ? -1 : 1;
67
+ if (a2 !== b2)
68
+ return a2 < b2 ? -1 : 1;
69
+ if (a3 !== b3)
70
+ return a3 < b3 ? -1 : 1;
71
+ return 0;
72
+ }
73
+ /**
74
+ * Recursively hash-compare two directories by content. Returns true if the
75
+ * byte contents of every file match (directory structure + file bytes).
76
+ *
77
+ * Used to detect hand-edited installs: if the installed version matches the
78
+ * bundled version but the bytes differ, the user (or a prior agent session)
79
+ * has customised the skill and we should not overwrite without --force.
80
+ */
81
+ function directoriesIdentical(a, b) {
82
+ try {
83
+ const aEntries = readdirSync(a).sort();
84
+ const bEntries = readdirSync(b).sort();
85
+ if (aEntries.length !== bEntries.length)
86
+ return false;
87
+ for (let i = 0; i < aEntries.length; i++) {
88
+ if (aEntries[i] !== bEntries[i])
89
+ return false;
90
+ const aChild = join(a, aEntries[i]);
91
+ const bChild = join(b, bEntries[i]);
92
+ const aStat = statSync(aChild);
93
+ const bStat = statSync(bChild);
94
+ if (aStat.isDirectory() !== bStat.isDirectory())
95
+ return false;
96
+ if (aStat.isDirectory()) {
97
+ if (!directoriesIdentical(aChild, bChild))
98
+ return false;
99
+ }
100
+ else {
101
+ const aBuf = readFileSync(aChild);
102
+ const bBuf = readFileSync(bChild);
103
+ if (!aBuf.equals(bBuf))
104
+ return false;
105
+ }
106
+ }
107
+ return true;
108
+ }
109
+ catch {
110
+ return false;
111
+ }
112
+ }
113
+ export function installSkills(options = {}) {
114
+ const sourceDir = resolveBundledSkillsDir();
115
+ if (!existsSync(sourceDir)) {
116
+ throw new Error(`Bundled skills directory not found at ${sourceDir}`);
117
+ }
118
+ const targetBase = getSkillsTargetDir(options.global ?? false);
119
+ const results = [];
120
+ const skills = readdirSync(sourceDir, { withFileTypes: true })
121
+ .filter(d => d.isDirectory())
122
+ .map(d => d.name);
123
+ for (const skill of skills) {
124
+ const src = join(sourceDir, skill);
125
+ const dest = join(targetBase, skill);
126
+ const bundledVersion = parseSkillVersion(join(src, 'SKILL.md')) ?? '0.0.0';
127
+ const installedVersion = existsSync(dest) ? parseSkillVersion(join(dest, 'SKILL.md')) : null;
128
+ let outcome;
129
+ if (!existsSync(dest)) {
130
+ outcome = 'installed';
131
+ }
132
+ else if (options.force) {
133
+ outcome = 'forced';
134
+ }
135
+ else if (installedVersion && compareVersions(installedVersion, bundledVersion) > 0) {
136
+ outcome = 'newer-local';
137
+ }
138
+ else if (installedVersion && compareVersions(installedVersion, bundledVersion) === 0) {
139
+ outcome = directoriesIdentical(src, dest) ? 'up-to-date' : 'hand-edited';
140
+ }
141
+ else {
142
+ outcome = 'updated';
143
+ }
144
+ if (outcome === 'installed' || outcome === 'updated' || outcome === 'forced') {
145
+ mkdirSync(dest, { recursive: true });
146
+ cpSync(src, dest, { recursive: true, force: true });
147
+ }
148
+ results.push({
149
+ skill,
150
+ outcome,
151
+ bundledVersion,
152
+ installedVersion,
153
+ targetPath: dest,
154
+ });
155
+ }
156
+ return results;
157
+ }
158
+ export function describeSkillsInstall(results, targetDir) {
159
+ if (results.length === 0)
160
+ return 'No skills to install.';
161
+ const lines = [];
162
+ for (const r of results) {
163
+ switch (r.outcome) {
164
+ case 'installed':
165
+ lines.push(` ✓ ${r.skill} v${r.bundledVersion} installed`);
166
+ break;
167
+ case 'updated':
168
+ lines.push(` ✓ ${r.skill} v${r.installedVersion} → v${r.bundledVersion} updated`);
169
+ break;
170
+ case 'forced':
171
+ lines.push(` ✓ ${r.skill} v${r.bundledVersion} installed (forced)`);
172
+ break;
173
+ case 'up-to-date':
174
+ lines.push(` • ${r.skill} v${r.bundledVersion} already installed`);
175
+ break;
176
+ case 'newer-local':
177
+ lines.push(` • ${r.skill} local v${r.installedVersion} is newer than bundled v${r.bundledVersion} — left as-is`);
178
+ break;
179
+ case 'hand-edited':
180
+ lines.push(` • ${r.skill} v${r.bundledVersion} already installed with local edits — left as-is (run with --force to overwrite)`);
181
+ break;
182
+ }
183
+ }
184
+ lines.push(` Skills directory: ${targetDir}`);
185
+ return lines.join('\n');
186
+ }
187
+ /**
188
+ * Produce a short one-line hint for the `auth login` summary, e.g.
189
+ * "Skill installed: agentled v0.2.0 → ~/.claude/skills/"
190
+ * "Skill already installed (v0.1.0), latest is v0.2.0 — run `agentled skills update` to refresh."
191
+ *
192
+ * Returns null if there is nothing worth showing.
193
+ */
194
+ export function summarizeForLoginBanner(results, targetDir) {
195
+ if (results.length === 0)
196
+ return null;
197
+ const fresh = results.filter(r => r.outcome === 'installed');
198
+ const stale = results.filter(r => r.outcome === 'newer-local' || r.outcome === 'hand-edited');
199
+ const updatable = results.filter(r => r.outcome === 'up-to-date' && r.installedVersion && r.bundledVersion && compareVersions(r.installedVersion, r.bundledVersion) < 0);
200
+ if (fresh.length > 0) {
201
+ const names = fresh.map(r => `${r.skill} v${r.bundledVersion}`).join(', ');
202
+ return `Installed Claude Code skill: ${names} → ${targetDir}`;
203
+ }
204
+ if (stale.length > 0) {
205
+ const r = stale[0];
206
+ return `Skill "${r.skill}" already installed (v${r.installedVersion ?? '?'}), bundled is v${r.bundledVersion} — run \`agentled skills update\` to refresh.`;
207
+ }
208
+ if (updatable.length > 0) {
209
+ const r = updatable[0];
210
+ return `Skill "${r.skill}" v${r.installedVersion} installed, v${r.bundledVersion} available — run \`agentled skills update\` to refresh.`;
211
+ }
212
+ return null;
213
+ }
214
+ //# sourceMappingURL=skills.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.js","sourceRoot":"","sources":["../../src/utils/skills.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentled/cli",
3
- "version": "0.1.5",
3
+ "version": "0.4.3",
4
4
  "description": "CLI for Agentled — manage workflows, apps, and knowledge from the command line. Zero context-window cost for AI agents.",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -28,6 +28,9 @@
28
28
  },
29
29
  "files": [
30
30
  "dist",
31
+ "skills",
32
+ "patterns",
33
+ "scaffolds",
31
34
  "README.md",
32
35
  "llms.txt",
33
36
  "llms-full.txt"
@@ -0,0 +1,107 @@
1
+ # 00 — Why agentic-ops
2
+
3
+ > The ops discipline that makes AI agents production-ready.
4
+
5
+ ---
6
+
7
+ ## The pitch deck demo works. Production doesn't.
8
+
9
+ You've seen it: an AI agent that looks brilliant in a demo — processes a lead, writes a personalized email, updates the CRM. Then you run it on 500 leads a week and the wheels fall off. Duplicates. Missing records. Costs 3× what you expected. No way to know what actually went through.
10
+
11
+ This isn't an AI problem. It's an **architecture problem**.
12
+
13
+ The fix has a name in every other engineering discipline: operations. CI/CD, observability, idempotency, retries, caching, audit trails — these didn't exist on day one of web development either. Developers invented them because raw execution didn't scale. Agentic workflows are at the same inflection point.
14
+
15
+ This is **agentic-ops**: the patterns that make the gap between "demo" and "production" crossable.
16
+
17
+ ---
18
+
19
+ ## 1. Unit economics collapse without dedup discipline
20
+
21
+ This is the argument that lands before developers hit the wall themselves.
22
+
23
+ You're processing 500 inbound leads per week. Your workflow enriches each one (5 credits). No dedup gate — the workflow polls every hour, no label marking what's been processed.
24
+
25
+ - Average lead appears in 3 polls before it's handled: **1,500 enrichments instead of 500**
26
+ - At 5 credits each: **5,000 wasted credits per week**
27
+ - At scale, you're paying for work you already did
28
+
29
+ This isn't hypothetical. It's the default outcome of any polling workflow without a dedup gate. See [02-dedup-gates](02-dedup-gates.md) for the fix.
30
+
31
+ ---
32
+
33
+ ## 2. Non-determinism at scale
34
+
35
+ A one-off prompt works once. Run the same prompt 1,000 times against your pipeline and you get 1,000 slightly different outputs — different field names, different score ranges, different JSON shapes. No two downstream steps can reliably consume the previous one.
36
+
37
+ Structured workflows define a **response contract**: the output schema is declared upfront, validated at runtime, and consistent across every execution. The AI fills in the values; the workflow enforces the shape.
38
+
39
+ Without this contract, you're parsing surprises, not outputs.
40
+
41
+ ---
42
+
43
+ ## 3. No audit trail, no trust
44
+
45
+ "The AI processed our deal flow last week" — can you tell me exactly which companies it looked at, what data it used, what score it assigned, and why three were dropped? If not, you can't trust it in any context that matters: regulated industries, board reporting, customer-facing processes.
46
+
47
+ Structured workflows produce **per-step execution records**: inputs, outputs, duration, status, timestamp. You can replay any run. You can compare two runs on the same input. You can show an auditor exactly what happened.
48
+
49
+ Ad-hoc prompts produce a chat message and nothing else.
50
+
51
+ ---
52
+
53
+ ## 4. Retries without idempotency destroy partial state
54
+
55
+ An AI agent that crashes halfway through is worse than one that never started. You have partial writes: some records enriched, some not; some CRM entries created, some missing. You don't know where it stopped.
56
+
57
+ Structured workflows solve this at two levels:
58
+ - **Step-level retry**: resume from the exact failed step with the same inputs — no re-running the work that succeeded
59
+ - **Idempotency gates**: dedup keys, label markers, and processed flags ensure a retried step produces the same outcome as the original, not a duplicate
60
+
61
+ See [07-error-handling](07-error-handling.md) and [02-dedup-gates](02-dedup-gates.md).
62
+
63
+ ---
64
+
65
+ ## 5. Caching requires stable step boundaries
66
+
67
+ Enriching the same LinkedIn company URL twice in the same workflow shouldn't hit the API twice. But caching requires a **stable cache key**: a defined input that uniquely identifies the computation.
68
+
69
+ Ad-hoc prompts have no stable key — the prompt is the key, and it changes with every rephrasing. Structured steps have explicit inputs, which means the platform can cache at the step level, deduplicate in-flight requests, and short-circuit repeated work.
70
+
71
+ No step boundary = no cache key = no caching.
72
+
73
+ ---
74
+
75
+ ## 6. Production requirements don't exist in raw prompting
76
+
77
+ Running AI agents at production scale without structured execution is like running a web server without a framework. You'll reinvent every wheel:
78
+
79
+ - **Observability**: knowing which step is running, how long it's taking, when it silently failed
80
+ - **Rate limiting**: preventing a burst of executions from hammering a downstream API
81
+ - **Concurrency control**: ensuring two parallel runs don't write conflicting records to the same CRM entry
82
+ - **Backpressure**: slowing intake when the processing queue backs up
83
+
84
+ These are solved problems in structured workflow systems. They don't exist as primitives in a prompt-and-hope architecture.
85
+
86
+ ---
87
+
88
+ ## 7. Human-in-the-loop gates need a first-class abstraction
89
+
90
+ "Have a human review the AI's output before it sends an email" sounds simple. In practice it requires: a UI to surface the output for review, a way to approve or reject, a mechanism to block the next step until the human acts, and a timeout path if they don't.
91
+
92
+ This is a first-class primitive in workflow systems — an approval gate with configurable behavior. In raw prompting, you build it from scratch every time.
93
+
94
+ Any workflow that touches customers, sends communications, or writes to a system of record should have a human-in-the-loop gate. See [09-human-in-the-loop](../v2/09-human-in-the-loop.md) (v2).
95
+
96
+ ---
97
+
98
+ ## The pattern
99
+
100
+ Every production failure in agentic workflows traces back to one of these seven gaps. The patterns in this repo address each one directly — not as theoretical advice, but as the specific implementations that fix them.
101
+
102
+ Start with the one that matches your current pain:
103
+ - Burning credits → [03-credit-efficiency](03-credit-efficiency.md)
104
+ - Processing duplicates → [02-dedup-gates](02-dedup-gates.md)
105
+ - Steps silently skipping → [06-conditional-routing](06-conditional-routing.md)
106
+ - Crashes with partial state → [07-error-handling](07-error-handling.md)
107
+ - Wrong trigger choice → [01-trigger-design](01-trigger-design.md)