@agentled/cli 0.6.7 → 0.7.2

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.
@@ -0,0 +1,414 @@
1
+ /**
2
+ * Bundled docs written into `~/.agentled/docs/` on `agentled setup` runs.
3
+ *
4
+ * Embedded as string constants so they ship with the CLI release (same
5
+ * pattern as GOTCHAS.md in workspace-folder.ts).
6
+ *
7
+ * **`docs/` is CLI-managed.** Treat the bundled files as read-only — they
8
+ * are unconditionally rewritten when `HOME_CONTENT_VERSION` advances
9
+ * past the on-disk marker. Anyone who wants to edit local notes should
10
+ * put them in `~/.agentled/docs/local/` (never touched by the bootstrap)
11
+ * or in the per-workspace `agentled_<slug>/` folder.
12
+ *
13
+ * `HOME_CONTENT_VERSION` is intentionally **decoupled from the CLI
14
+ * package version** — it is an opaque integer that bumps only when one
15
+ * of the constants below changes. A CLI patch bump that touches no doc
16
+ * content does not refresh `~/.agentled/`.
17
+ */
18
+ /**
19
+ * Bump this every time any HOME_README_MD / WORKFLOW_SHAPE_MD /
20
+ * GETTING_STARTED_MD / GOTCHAS_MD / PATTERNS_MD constant changes.
21
+ *
22
+ * Do NOT pin to the CLI semver — that bumps for unrelated reasons and
23
+ * causes spurious doc rewrites on every patch release.
24
+ */
25
+ export const HOME_CONTENT_VERSION = '3';
26
+ export const HOME_README_MD = `# AgentLed
27
+
28
+ You've installed the AgentLed CLI. Your AI agent (Claude Code, Codex, Cursor, Claude Desktop, Windsurf) can now build and run workflows for you.
29
+
30
+ ## Talk to your agent
31
+
32
+ Once \`agentled setup\` is done and you've restarted your MCP client, just describe what you want. The agent has access to AgentLed's MCP tools, your workspace's knowledge graph, and 100+ integrations.
33
+
34
+ Try one:
35
+ - "Source fintech CTOs in Europe via search and LinkedIn, score by ICP fit, email me the top 10 daily."
36
+ - "Qualify inbound form submissions and route the high-score ones to a Slack channel."
37
+ - "Pull competitor pricing pages weekly, summarize changes, send a diff report."
38
+
39
+ ## What lives here
40
+
41
+ - \`config.json\` — saved workspace profiles (managed by \`agentled auth\`).
42
+ - \`docs/\` — brief design guide your agent reads on session start. **CLI-managed: treat as read-only.** Files here are rewritten when the bundled doc version advances.
43
+ - \`docs/local/\` — your own notes. **Never overwritten by the CLI.** Put any edits or additions here.
44
+ - \`examples/scaffolds/\` — preflight-clean pipeline templates your agent adapts to your intent. Also CLI-managed.
45
+
46
+ Per-workspace artifacts (logs, dryruns, decisions, drafts) live in \`agentled_<workspace-slug>/\` in your project directory — one folder per workspace.
47
+
48
+ ## CLI commands
49
+
50
+ \`\`\`
51
+ agentled --help # list commands
52
+ agentled auth current # active workspace
53
+ agentled workflows list # workflows in your workspace
54
+ agentled examples # browse pattern templates
55
+ \`\`\`
56
+
57
+ ## Open patterns reference
58
+
59
+ For extended workflow patterns and anti-patterns beyond the bundled scaffolds, see the public agentic-ops repo: https://github.com/Agentled/agentic-ops. Optional reading — the bundled \`docs/\` and \`examples/scaffolds/\` are sufficient for first-workflow building.
60
+ `;
61
+ export const WORKFLOW_SHAPE_MD = `# Workflow shape — source → list → orchestrator → outreach
62
+
63
+ The canonical AgentLed workflow shape, optimized for re-runnable, dedup-safe pipelines.
64
+
65
+ ## The list is the spine
66
+
67
+ A KG list (e.g. \`kg.list.leads\`) holds every entity your business cares about. Multiple sourcing workflows write into the same list. One orchestrator workflow reads from it, processes, and transitions row state.
68
+
69
+ Two indexes make this efficient:
70
+
71
+ 1. **\`userKey\`** — caller-supplied dedup index. Use a stable identifier per row (domain, LinkedIn URL, email hash). \`kg.upsert-rows\` with the same \`userKey\` writes to the same row, every time, forever. No table scan, no duplicate explosion.
72
+ 2. **\`status\`** — the queue marker. New rows start at \`status: "new"\`. The orchestrator filters by status, processes only rows in the relevant state, and transitions status as it goes (\`scored\`, \`qualified\`, \`contacted\`, \`rejected\`).
73
+
74
+ ## Sourcing workflows (1+)
75
+
76
+ Each sourcing workflow has one job: find entities, write them with a \`userKey\` and \`status: "new"\`. Use \`mergeStrategy: "merge"\` so downstream-added fields (scores, notes) survive a re-source. Many sourcing workflows can write to the same list.
77
+
78
+ \`\`\`json
79
+ {
80
+ "id": "save-to-list",
81
+ "type": "appAction",
82
+ "app": { "id": "kg", "actionId": "kg.upsert-rows", "source": "native" },
83
+ "stepInputData": {
84
+ "listKey": "leads",
85
+ "rows": "{{steps.extract.items}}",
86
+ "mergeStrategy": "merge",
87
+ "status": "new"
88
+ }
89
+ }
90
+ \`\`\`
91
+
92
+ > Note: pass \`rows\` directly as the template variable — do NOT wrap it in \`JSON.stringify\` or quote-escape the array. The serializer inlines the raw value (see GOTCHAS.md #12). The \`filters\` field on \`kg.read-list\` (below) is the exception — it expects a JSON-string body, not an array, so the escaped object literal is correct there.
93
+
94
+ ## Orchestrator workflow (1)
95
+
96
+ Schedule trigger → \`kg.read-list\` filtered by \`status: "new"\` → loop → score / qualify / route → \`kg.update-rows\` to transition status.
97
+
98
+ \`\`\`json
99
+ // Step 1: read pending rows
100
+ {
101
+ "id": "read-pending",
102
+ "type": "appAction",
103
+ "app": { "id": "kg", "actionId": "kg.read-list", "source": "native" },
104
+ "stepInputData": { "listKey": "leads", "filters": "{\\"status\\": \\"new\\"}", "limit": "50" }
105
+ }
106
+
107
+ // Step N: transition status
108
+ {
109
+ "id": "mark-scored",
110
+ "type": "appAction",
111
+ "app": { "id": "kg", "actionId": "kg.update-rows", "source": "native" },
112
+ "stepInputData": {
113
+ "listKey": "leads",
114
+ "rowIds": "{{steps.score.processedIds}}",
115
+ "fieldUpdates": "{\\"status\\": \\"scored\\"}"
116
+ }
117
+ }
118
+ \`\`\`
119
+
120
+ ## Outreach workflow (1, optional)
121
+
122
+ Often folded into the orchestrator. When separate: schedule trigger → \`kg.read-list\` filtered by \`status: "qualified"\` → compose email (with approval gate) → \`schedule-email\` → mark \`status: "contacted"\`.
123
+
124
+ Why separate: outreach has different cadence (e.g. daily, batch-limited) than scoring (continuous), and you may want different approval gates per channel.
125
+
126
+ ## Status conventions
127
+
128
+ | Value | Meaning |
129
+ |-------|---------|
130
+ | \`new\` | Sourced, not yet processed |
131
+ | \`scored\` | Enriched + scored, awaiting routing |
132
+ | \`qualified\` | Passes ICP / threshold, ready for outreach |
133
+ | \`rejected\` | Failed scoring criteria |
134
+ | \`contacted\` | Outreach sent |
135
+ | \`replied\` | Reply received (set by an inbound workflow) |
136
+
137
+ Use whatever values fit your domain. The pattern is: sourcing always sets one status, the orchestrator transitions through ≥1 status, reads always filter by status.
138
+
139
+ ## Why the spine matters
140
+
141
+ - Multiple sourcing channels converge — one canonical list, no fan-out logic in each producer.
142
+ - Re-running a source is idempotent — \`userKey\` dedup.
143
+ - Re-running the orchestrator is idempotent — status filter excludes done rows.
144
+ - Each phase has its own cadence — sourcing daily, orchestrator hourly, outreach business hours.
145
+ - Failures are scoped — a bad source doesn't pollute scoring; a bad scorer doesn't break sourcing.
146
+
147
+ ## Pausing for human input — decouple via the list
148
+
149
+ When a workflow needs human input partway through (e.g., "meeting done, capture the outcome and transcript URL, then continue scoring"), **don't try to pause inside one workflow**. Split it across the KG list spine — same shape as everything else.
150
+
151
+ \`\`\`
152
+ Workflow A (the producer)
153
+ … reaches the point that needs human input …
154
+ → kg.update-rows: status = "needs-meeting-outcome"
155
+ → milestone (A is done; row sits in the list)
156
+
157
+ Workflow B (user-triggered, manual)
158
+ → trigger: manual, with input page asking for:
159
+ - meeting_outcome (text)
160
+ - transcript_url (url)
161
+ → kg.update-rows: status = "input-received", fieldUpdates = { outcome, transcript }
162
+ → milestone
163
+
164
+ Workflow C (the consumer, scheduled)
165
+ → kg.read-list filtered by status = "input-received"
166
+ → … continue scoring / qualifying using outcome + transcript …
167
+ → kg.update-rows: status = "scored"
168
+ \`\`\`
169
+
170
+ Why decouple:
171
+ - Each workflow has its own cadence and trigger — the producer runs on schedule, the user-triggered B runs whenever the user has the data, the consumer runs on schedule. None blocks the other.
172
+ - The KG row carries the state. If the user fills in the form a week later, it just works — nothing was hanging in memory waiting.
173
+ - A new agent (or a teammate) can act on rows in any state at any time — the substrate is shared.
174
+ - You can have multiple producers, multiple human-input forms (different roles, different channels), and one consumer. Or any other shape that fits.
175
+
176
+ In-workflow pause-with-input is possible in some cases via \`milestone\` with a configured input page, but the AgentLed-native approach for human-in-the-loop is the decoupled pattern above. Reach for it first.
177
+
178
+ ## Where to put what
179
+
180
+ | You want to… | Use |
181
+ |--------------|-----|
182
+ | Capture per-execution input from a user | \`context.inputPages\` on the workflow |
183
+ | Capture per-execution input from a public form / unauthed user | a workflow with a public form trigger and a public-form share configuration |
184
+ | Reference workspace-wide context (ICP, tone, products, brand voice) | \`knowledge.* text\` (read via \`kg.read-text\`, written via \`kg.upsert-text\`) — shared across workflows and agents |
185
+ | Hand a result back to the user as a viewable report | \`aiAction\` (structured output) → renderer config on that step → \`share\` step (creates URL) → email notification with the URL |
186
+ | Pause one workflow until a human provides extra data | Split into two workflows + a status transition on the KG row (see "Pausing for human input" above) |
187
+ | Track business value once a workflow is validated | \`metadata.roi\` + \`eventSummary\` per run + an \`entryConditions\` gate that skips the run when inputs wouldn't move the needle |
188
+
189
+ ### Report-and-share-back sequence
190
+
191
+ The canonical "give me a report and email me a link" sequence:
192
+
193
+ \`\`\`json
194
+ // Step 1: aiAction with structured output the renderer can read
195
+ {
196
+ "id": "compose-report",
197
+ "type": "aiAction",
198
+ "pipelineStepPrompt": {
199
+ "template": "… build the report here …",
200
+ "responseStructure": { "title": "string", "sections": [{ "heading": "string", "body": "string" }] }
201
+ },
202
+ "renderer": { "type": "Config", "config": { "layout": "report" } },
203
+ "creditCost": 20,
204
+ "next": { "stepId": "make-share" }
205
+ }
206
+
207
+ // Step 2: share step → mints a public URL pointing at compose-report's output
208
+ {
209
+ "id": "make-share",
210
+ "type": "share",
211
+ "shareConfig": { "outputSteps": ["compose-report"], "visibility": "link" },
212
+ "next": { "stepId": "notify" }
213
+ }
214
+
215
+ // Step 3: email notification with the share URL inlined
216
+ {
217
+ "id": "notify",
218
+ "type": "aiAction",
219
+ "pipelineStepPrompt": {
220
+ "type": "email",
221
+ "template": "Draft a 2-line email letting the user know their report is ready. Include the link.",
222
+ "responseStructure": {
223
+ "email": {
224
+ "from": "{{context.outreachProfile.fromEmail}}",
225
+ "to": "{{input.recipient_email}}",
226
+ "subject": "Your report is ready",
227
+ "body": "<p>Your report: <a href=\\"{{steps.make-share.url}}\\">view it here</a>.</p>",
228
+ "bodyType": "html"
229
+ }
230
+ }
231
+ },
232
+ "onApproval": { "action": "schedule-email" },
233
+ "next": { "stepId": "done" }
234
+ }
235
+ \`\`\`
236
+
237
+ ### Public input pattern
238
+
239
+ For workflows triggered by user-submitted forms (no auth required), use a public-form trigger and a share configuration that exposes the form at a stable slug. The form's submission payload becomes the workflow input. Same workflow shape applies; only the trigger differs.
240
+
241
+ ### Post-validation: ROI + business metrics
242
+
243
+ Once a workflow is validated and running:
244
+
245
+ 1. **ROI tracking** — add an \`metadata.roi\` block with hours saved per run, dollar value, conversion lift. Surfaces in the workflow header and the workspace metrics dashboard.
246
+ 2. **Per-run \`eventSummary\`** — emit a small structured log: count processed, count qualified, total credits, success rate. Powers the metrics dashboard and lets agents reason about workflow health from the KG.
247
+ 3. **\`entryConditions\` gate** — skip the run when its inputs wouldn't actually move the needle (e.g., \`kg.read-list\` returned 0 new rows, or upstream signal is below threshold). Avoids credit waste on no-op runs and produces cleaner ROI numbers.
248
+
249
+ Full pattern reference (step types, schemas, all gotchas) is in the AgentLed skill loaded into your AI agent on session start.
250
+ `;
251
+ export const GETTING_STARTED_MD = `# Your first end-to-end workflow
252
+
253
+ Five minutes from "I have an idea" to "my agent built it".
254
+
255
+ ## 1. Describe intent in one sentence
256
+
257
+ Good prompts look like:
258
+
259
+ - "Source 50 fintech startups in Europe via search, write them to a leads list, score by ICP fit, and email me the top 10 weekly."
260
+ - "When a form is submitted, qualify against my ICP knowledge and post the high-score ones to #sales-qualified in Slack."
261
+
262
+ Bad prompts look like:
263
+
264
+ - "Build me a CRM." (Too broad — the agent doesn't know what to start with.)
265
+ - "Use aiAction with workspace_memory tool." (Too prescriptive — you're authoring the pipeline, not the agent.)
266
+
267
+ ## 2. Let the agent orient
268
+
269
+ The agent will run \`workspace inspect\` (or the equivalent MCP tools) to look at:
270
+
271
+ - Your existing KG lists (so it can reuse rather than create duplicates).
272
+ - Connected apps (LinkedIn, Hunter, Gmail, Slack — only what's authed will work).
273
+ - Existing workflows (it won't recreate one you already have).
274
+ - Existing agents and routines.
275
+
276
+ This usually triggers 1-3 short questions back. Answer them and move on.
277
+
278
+ ## 3. Build incrementally
279
+
280
+ The agent will start from a scaffold (one of \`~/.agentled/examples/scaffolds/*.json\`), adapt it to your intent, and add steps one at a time. Per-step validation catches type mismatches, bad model IDs, and template-variable typos before the full workflow is saved.
281
+
282
+ Do not ask the agent to dump a 30-step JSON in one shot. The skill explains why.
283
+
284
+ ## 4. Validate, then run small
285
+
286
+ \`\`\`
287
+ agentled workflows validate <workflowId> # graph-level checks
288
+ agentled workflows lint <file.json> # static gotcha catches
289
+ \`\`\`
290
+
291
+ First execution: feed it 3-5 sample inputs, not 500. Watch the credit count. If something is wrong, fix it cheap.
292
+
293
+ ## 5. Promote to production
294
+
295
+ \`\`\`
296
+ agentled workflows publish <workflowId> --status live
297
+ \`\`\`
298
+
299
+ Then schedule it (or trigger it manually, or wire it to a webhook). Iterate.
300
+
301
+ ## What good looks like
302
+
303
+ - Sourcing on its own schedule, writing to a list with \`userKey\` dedup.
304
+ - An orchestrator that filters by \`status\` so it never re-processes done rows.
305
+ - Every branch terminates (\`milestone\` for top-level workflows, \`return\` for child workflows, or no \`next.stepId\`). \`milestone\` is a labeled endpoint, not a required step — a workflow with no \`next\` is already terminal.
306
+ - Human-in-the-loop steps decoupled across workflows via the KG list (see WORKFLOW-SHAPE.md "Pausing for human input").
307
+ - An outreach step (or workflow) gated on approval before sending.
308
+ - ROI metadata + \`eventSummary\` + an \`entryConditions\` gate — added once the workflow is validated.
309
+
310
+ For the canonical shape and the "where to put what" reference, see \`WORKFLOW-SHAPE.md\` in this folder. For silent failure modes see \`GOTCHAS.md\`.
311
+ `;
312
+ export const GOTCHAS_MD = `# AgentLed — documented silent failure modes
313
+
314
+ These pass JSON syntax validation but silently misbehave at runtime.
315
+ Run \`agentled workflows lint <file>\` to catch them statically before deploying.
316
+
317
+ ---
318
+
319
+ ## 1. \`criteria\` not \`conditions\` in entryConditions
320
+
321
+ **Wrong:** \`{ "entryConditions": { "conditions": [...] } }\`
322
+ **Correct:** \`{ "entryConditions": { "criteria": [...] } }\`
323
+
324
+ The executor reads \`entryConditions.criteria\`. The key \`conditions\` is silently ignored.
325
+
326
+ ## 2. \`variable\` not \`field\` in criteria items
327
+
328
+ **Wrong:** \`{ "field": "{{steps.x.score}}", "operator": ">", "value": 70 }\`
329
+ **Correct:** \`{ "variable": "{{steps.x.score}}", "operator": ">", "value": 70 }\`
330
+
331
+ Using \`field\` causes the criterion to be silently skipped.
332
+
333
+ ## 3. Gmail label_id must be the internal Label_XXXX ID
334
+
335
+ Gmail's API requires \`Label_XXXXXXXXXX\` IDs, not display names. Add a \`GMAIL_CREATE_LABEL\` step before and use \`{{steps.ensure-label.id}}\`.
336
+
337
+ ## 4. \`aiActionWithTools\` with no tools
338
+
339
+ A step with \`type: "aiActionWithTools"\` must have at least one tool in \`step.tools\` or \`step.agent.tools\`. Valid \`builtinType\` values: \`web_search\`, \`file_search\`, \`code_interpreter\`, \`fetch_website_content\`, \`kg_search\`, \`kg_traverse\`, \`kg_nodes\`, \`kg_write\`, \`workspace_memory\`.
340
+
341
+ ## 5. Email steps need type + approval action + outreachProfile
342
+
343
+ Three required pieces:
344
+ - \`pipelineStepPrompt.type: "email"\`
345
+ - \`onApproval.action: "schedule-email"\`
346
+ - \`outreachProfile\` input page in \`context.inputPages\`
347
+
348
+ Missing the schedule-email action means the email is drafted but never sent.
349
+
350
+ ## 6. Only the first step in a loop gets \`loopConfig\`
351
+
352
+ \`loopConfig\` must be on the first step in the loop chain only. Subsequent steps inside the loop iterate automatically.
353
+
354
+ ## 7. Don't pass raw \`{{input.*}}\` directly to search APIs
355
+
356
+ Add an aiAction step before the search that generates optimized queries. Raw user input makes poor search queries.
357
+
358
+ ## 8. Child workflows use \`return\`; \`internal: true\` is for child-only workflows
359
+
360
+ If a workflow is called via \`agentled.call-workflow\` (i.e., a **child workflow** invoked by another workflow rather than a user), use \`type: "return"\` instead of \`milestone\`. \`milestone\` produces no return data — the parent receives nothing.
361
+
362
+ Also set \`context.executionInputConfig.internal: true\` on the **child** workflow — this hides it from the user-triggered list.
363
+
364
+ **Top-level workflows** triggered directly by users (manual, schedule, webhook, public form, app event) keep \`milestone\` and **do NOT** set \`internal: true\`. Setting \`internal: true\` on a user-facing workflow hides it from its intended caller.
365
+
366
+ ## 9. Model IDs are internal format, not Anthropic format
367
+
368
+ Wrong: \`claude-sonnet-4-6\`. Correct: \`claude-4-6-sonnet\`. Run \`agentled models list\` for valid internal IDs.
369
+
370
+ ## 10. Native app actionId must include appId prefix
371
+
372
+ Wrong: \`{ "id": "kg", "actionId": "read-list" }\`
373
+ Correct: \`{ "id": "kg", "actionId": "kg.read-list" }\`
374
+
375
+ ## 11. \`loop_completion\` criteria requires \`onCriteriaFail: "wait"\`
376
+
377
+ Without \`onCriteriaFail: "wait"\`, the step skips instead of blocking until the loop finishes. The \`stepId\` field is also required.
378
+
379
+ ## 12. Arrays in JSON template strings — don't JSON.stringify
380
+
381
+ The serializer detects when a template variable is the sole content of a JSON field and inlines the raw value. Pass \`{ "items": "{{steps.x.items}}" }\` directly — no stringify needed. (Note: \`kg.read-list\` \`filters\` is the exception — it expects a JSON-string body, see WORKFLOW-SHAPE.md.)
382
+
383
+ ## 13. \`kg.upsert-rows\` needs \`userKey\` for dedup; \`kg.add-rows\` always inserts
384
+
385
+ \`kg.upsert-rows\` with \`userKey\`: same key = same row, cross-run dedup O(1).
386
+ \`kg.add-rows\`: always inserts a new row, duplicates accumulate.
387
+ Use \`mergeStrategy: "merge"\` to preserve downstream-added fields.
388
+ `;
389
+ export const PATTERNS_MD = `# Pattern index — \`~/.agentled/examples/scaffolds/\`
390
+
391
+ Preflight-clean pipeline templates. Pick the closest match to your intent and adapt — don't author from scratch.
392
+
393
+ | Scaffold | Shape | Use when |
394
+ |----------|-------|----------|
395
+ | \`minimal.json\` | trigger → milestone | smoke-testing the pipeline runner |
396
+ | \`email-polling-dedup.json\` | schedule → fetch emails (label dedup) → loop → add label | inbound email triage / processing without double-handling |
397
+ | \`lead-scoring-kg.json\` | trigger → \`kg.read-list\` → AI scoring loop → \`knowledgeSync\` | the orchestrator phase of source → list → orchestrator |
398
+ | \`list-match-email.json\` | trigger → \`kg.read-list\` → AI match → composed email (approval gate) → \`knowledgeSync\` | outreach phase: pull qualified rows, draft email, gate on approval |
399
+ | \`extract-threshold-alert.json\` | trigger → AI extract → threshold check → external update → conditional Slack → \`knowledgeSync\` | conditional routing on AI-extracted scores |
400
+ | \`ai-with-tools.json\` | trigger → \`aiActionWithTools\` (web_search + workspace_memory) → milestone | starter for agentic steps that need to call runtime tools |
401
+
402
+ ## Mapping to the canonical shape
403
+
404
+ The \`source → list → orchestrator → outreach\` flow uses these scaffolds in combination:
405
+
406
+ - **Sourcing** (1+ workflows feeding the same list): start from a scaffold that ends in \`kg.upsert-rows\` to your list, with \`userKey\` and \`status: "new"\`. The bundled \`email-polling-dedup\` is the closest starter; adapt the source step to your channel (search, scrape, form, webhook).
407
+ - **Orchestrator** (reads pending status, processes, transitions): start from \`lead-scoring-kg\` and add a final \`kg.update-rows\` step that sets \`status: "scored"\` (or \`qualified\` / \`rejected\`).
408
+ - **Outreach** (reads qualified, sends with approval): start from \`list-match-email\`, then add the \`kg.update-rows\` to mark \`status: "contacted"\`.
409
+ - **Reports** (generate output, share, notify): see the "Report-and-share-back sequence" section in \`WORKFLOW-SHAPE.md\` — \`aiAction\` → \`share\` step → email notification.
410
+ - **Human-in-the-loop** (workflow needs human input partway through): see "Pausing for human input" in \`WORKFLOW-SHAPE.md\` — split into producer + manual-trigger input form + consumer, all keyed on a status transition in the KG row.
411
+
412
+ For the full pattern shape and why \`userKey\` + \`status\` matter as indexes, see \`WORKFLOW-SHAPE.md\` in this folder.
413
+ `;
414
+ //# sourceMappingURL=agentled-home-content.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"agentled-home-content.js","sourceRoot":"","sources":["../../src/utils/agentled-home-content.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AAExC,MAAM,CAAC,MAAM,cAAc,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkC7B,CAAC;AAEF,MAAM,CAAC,MAAM,iBAAiB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA6LhC,CAAC;AAEF,MAAM,CAAC,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4DjC,CAAC;AAEF,MAAM,CAAC,MAAM,UAAU,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA4EzB,CAAC;AAEF,MAAM,CAAC,MAAM,WAAW,GAAG;;;;;;;;;;;;;;;;;;;;;;;;CAwB1B,CAAC"}
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Bootstrap `~/.agentled/` on `agentled setup` runs.
3
+ *
4
+ * Writes:
5
+ * ~/.agentled/README.md (top-level pointer)
6
+ * ~/.agentled/.content-version (refresh marker)
7
+ * ~/.agentled/docs/WORKFLOW-SHAPE.md (canonical shape)
8
+ * ~/.agentled/docs/GETTING-STARTED.md (5-min first workflow)
9
+ * ~/.agentled/docs/GOTCHAS.md (silent failure modes)
10
+ * ~/.agentled/docs/PATTERNS.md (scaffold index)
11
+ * ~/.agentled/examples/scaffolds/* (copied from packages/cli/scaffolds/)
12
+ *
13
+ * **`docs/` and `examples/scaffolds/` are CLI-managed.** When the
14
+ * bundled `HOME_CONTENT_VERSION` advances past the on-disk marker, the
15
+ * bootstrap unconditionally rewrites every bundled file — user edits
16
+ * to those files WILL be overwritten. Treat them as read-only and put
17
+ * your own notes in `~/.agentled/docs/local/` (never touched) or in
18
+ * the per-workspace `agentled_<slug>/` folder.
19
+ *
20
+ * `config.json` is never touched.
21
+ *
22
+ * `HOME_CONTENT_VERSION` is decoupled from the CLI semver — it bumps
23
+ * only when bundled docs change, so a CLI patch release with no doc
24
+ * change does NOT trigger a rewrite.
25
+ *
26
+ * Idempotent: a re-run with the same marker version is a no-op.
27
+ */
28
+ export interface BootstrapResult {
29
+ homeDir: string;
30
+ /** True when this run wrote or refreshed any docs. */
31
+ refreshed: boolean;
32
+ /** Number of scaffold files copied into examples/scaffolds/. */
33
+ scaffoldsCopied: number;
34
+ /** Marker version after this run — matches HOME_CONTENT_VERSION on success. */
35
+ version: string;
36
+ }
37
+ /**
38
+ * Idempotent. Creates `~/.agentled/` if missing and rewrites the
39
+ * bundled docs + scaffolds when the on-disk content version is older
40
+ * than `HOME_CONTENT_VERSION`. Bundled files are unconditionally
41
+ * overwritten on refresh; never touches `config.json` or any file
42
+ * under `docs/local/`.
43
+ */
44
+ export declare function bootstrapAgentledHome(): BootstrapResult;
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Bootstrap `~/.agentled/` on `agentled setup` runs.
3
+ *
4
+ * Writes:
5
+ * ~/.agentled/README.md (top-level pointer)
6
+ * ~/.agentled/.content-version (refresh marker)
7
+ * ~/.agentled/docs/WORKFLOW-SHAPE.md (canonical shape)
8
+ * ~/.agentled/docs/GETTING-STARTED.md (5-min first workflow)
9
+ * ~/.agentled/docs/GOTCHAS.md (silent failure modes)
10
+ * ~/.agentled/docs/PATTERNS.md (scaffold index)
11
+ * ~/.agentled/examples/scaffolds/* (copied from packages/cli/scaffolds/)
12
+ *
13
+ * **`docs/` and `examples/scaffolds/` are CLI-managed.** When the
14
+ * bundled `HOME_CONTENT_VERSION` advances past the on-disk marker, the
15
+ * bootstrap unconditionally rewrites every bundled file — user edits
16
+ * to those files WILL be overwritten. Treat them as read-only and put
17
+ * your own notes in `~/.agentled/docs/local/` (never touched) or in
18
+ * the per-workspace `agentled_<slug>/` folder.
19
+ *
20
+ * `config.json` is never touched.
21
+ *
22
+ * `HOME_CONTENT_VERSION` is decoupled from the CLI semver — it bumps
23
+ * only when bundled docs change, so a CLI patch release with no doc
24
+ * change does NOT trigger a rewrite.
25
+ *
26
+ * Idempotent: a re-run with the same marker version is a no-op.
27
+ */
28
+ import { existsSync, mkdirSync, writeFileSync, readFileSync, readdirSync, copyFileSync } from 'node:fs';
29
+ import { join } from 'node:path';
30
+ import { homedir } from 'node:os';
31
+ import { bundledScaffoldsDir } from './workspace-folder.js';
32
+ import { HOME_CONTENT_VERSION, HOME_README_MD, WORKFLOW_SHAPE_MD, GETTING_STARTED_MD, GOTCHAS_MD, PATTERNS_MD, } from './agentled-home-content.js';
33
+ const MARKER_FILE = '.content-version';
34
+ function readMarker(homeDir) {
35
+ const path = join(homeDir, MARKER_FILE);
36
+ if (!existsSync(path))
37
+ return null;
38
+ try {
39
+ return readFileSync(path, 'utf-8').trim() || null;
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ function writeMarker(homeDir) {
46
+ writeFileSync(join(homeDir, MARKER_FILE), HOME_CONTENT_VERSION + '\n');
47
+ }
48
+ /**
49
+ * Compare integer-like marker versions: -1, 0, 1.
50
+ *
51
+ * `HOME_CONTENT_VERSION` is intentionally an opaque integer string
52
+ * ("1", "2", …), but parsed defensively in case a future maintainer
53
+ * uses a semver-shaped value.
54
+ */
55
+ function compareVersions(a, b) {
56
+ const parse = (v) => v.replace(/^v/, '').split('-')[0].split('.').map(n => parseInt(n, 10) || 0);
57
+ const [a1, a2 = 0, a3 = 0] = parse(a);
58
+ const [b1, b2 = 0, b3 = 0] = parse(b);
59
+ if (a1 !== b1)
60
+ return a1 < b1 ? -1 : 1;
61
+ if (a2 !== b2)
62
+ return a2 < b2 ? -1 : 1;
63
+ if (a3 !== b3)
64
+ return a3 < b3 ? -1 : 1;
65
+ return 0;
66
+ }
67
+ function shouldRefresh(homeDir) {
68
+ const installed = readMarker(homeDir);
69
+ if (!installed)
70
+ return true; // first run
71
+ return compareVersions(installed, HOME_CONTENT_VERSION) < 0;
72
+ }
73
+ /**
74
+ * Copy bundled scaffold assets into `examples/scaffolds/`. Includes
75
+ * any `.json` pipeline scaffold and any `.md` companion documentation.
76
+ * Other extensions are skipped — keep this whitelist tight so a stray
77
+ * file in `packages/cli/scaffolds/` never lands in user-visible space.
78
+ */
79
+ function copyBundledScaffolds(targetDir) {
80
+ const sourceDir = bundledScaffoldsDir();
81
+ if (!existsSync(sourceDir))
82
+ return 0;
83
+ mkdirSync(targetDir, { recursive: true });
84
+ let count = 0;
85
+ for (const entry of readdirSync(sourceDir)) {
86
+ if (!entry.endsWith('.json') && !entry.endsWith('.md'))
87
+ continue;
88
+ const src = join(sourceDir, entry);
89
+ const dest = join(targetDir, entry);
90
+ copyFileSync(src, dest);
91
+ count++;
92
+ }
93
+ return count;
94
+ }
95
+ /**
96
+ * Idempotent. Creates `~/.agentled/` if missing and rewrites the
97
+ * bundled docs + scaffolds when the on-disk content version is older
98
+ * than `HOME_CONTENT_VERSION`. Bundled files are unconditionally
99
+ * overwritten on refresh; never touches `config.json` or any file
100
+ * under `docs/local/`.
101
+ */
102
+ export function bootstrapAgentledHome() {
103
+ const homeDir = join(homedir(), '.agentled');
104
+ const docsDir = join(homeDir, 'docs');
105
+ const examplesDir = join(homeDir, 'examples');
106
+ const scaffoldsDir = join(examplesDir, 'scaffolds');
107
+ if (!existsSync(homeDir))
108
+ mkdirSync(homeDir, { recursive: true });
109
+ if (!shouldRefresh(homeDir)) {
110
+ return {
111
+ homeDir,
112
+ refreshed: false,
113
+ scaffoldsCopied: 0,
114
+ version: readMarker(homeDir) ?? HOME_CONTENT_VERSION,
115
+ };
116
+ }
117
+ mkdirSync(docsDir, { recursive: true });
118
+ mkdirSync(scaffoldsDir, { recursive: true });
119
+ writeFileSync(join(homeDir, 'README.md'), HOME_README_MD);
120
+ writeFileSync(join(docsDir, 'WORKFLOW-SHAPE.md'), WORKFLOW_SHAPE_MD);
121
+ writeFileSync(join(docsDir, 'GETTING-STARTED.md'), GETTING_STARTED_MD);
122
+ writeFileSync(join(docsDir, 'GOTCHAS.md'), GOTCHAS_MD);
123
+ writeFileSync(join(docsDir, 'PATTERNS.md'), PATTERNS_MD);
124
+ const scaffoldsCopied = copyBundledScaffolds(scaffoldsDir);
125
+ writeMarker(homeDir);
126
+ return {
127
+ homeDir,
128
+ refreshed: true,
129
+ scaffoldsCopied,
130
+ version: HOME_CONTENT_VERSION,
131
+ };
132
+ }
133
+ //# sourceMappingURL=home-bootstrap.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home-bootstrap.js","sourceRoot":"","sources":["../../src/utils/home-bootstrap.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Read `knowledge.company.profile` (and `.products`) from the workspace KG.
3
+ *
4
+ * Used by `agentled setup` to decide whether to prompt the user for company
5
+ * information or skip straight to "workspace already configured". We probe
6
+ * only the new keys; legacy `.company` / `company.offering` are not checked
7
+ * — we focus on new clients and keep this clean.
8
+ *
9
+ * Uses the typed `AgentledApiClient.getKnowledgeText` surface. Failures are
10
+ * non-fatal: setup must not break on a network blip or a missing endpoint.
11
+ */
12
+ import { AgentledApiClient } from '@agentled/core';
13
+ export interface KnowledgeProbeResult {
14
+ /** Has the user (or an agent) populated the canonical company profile yet? */
15
+ profilePresent: boolean;
16
+ productsPresent: boolean;
17
+ /** Short snippet of the profile if present (first ~120 chars) for the summary line. */
18
+ profilePreview?: string;
19
+ /** Set if the probe failed entirely (network, permissions). Treat as "unknown". */
20
+ error?: string;
21
+ }
22
+ export declare function probeCompanyKnowledge(client: AgentledApiClient): Promise<KnowledgeProbeResult>;
23
+ export declare function summarizeKnowledgeProbe(r: KnowledgeProbeResult): string;