agentix-cli 0.3.0 → 0.5.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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AgentX
2
2
 
3
- **Self-hosted multi-agent orchestrator.** Routes messages from Telegram, WhatsApp, Discord, crons, and cross-machine A2A mesh to AI agents running on Claude Code, OpenAI, Ollama, or any LLM provider.
3
+ **Self-hosted multi-agent orchestrator.** Routes messages from Telegram, WhatsApp, Discord, GitLab, crons, webhooks, and cross-machine A2A mesh to AI agents running on Claude Code, OpenAI, Ollama, or any LLM provider.
4
4
 
5
5
  > **Experimental.** Built as a self-hosted, bring-your-own-key alternative to third-party AI orchestrators affected by [Anthropic's updated terms of use](https://www.anthropic.com/policies). You run it on your own machines with your own API keys or Claude subscription.
6
6
 
@@ -13,138 +13,96 @@ npm install -g agentix-cli
13
13
  ## Quick start
14
14
 
15
15
  ```bash
16
- # 1. Initialize
17
- agentx init
18
-
19
- # 2. Add an agent (interactive)
20
- agentx agent add
21
-
22
- # 3. Add a Telegram bot (interactive, verifies token)
23
- agentx channel add
24
-
25
- # 4. Start
26
- agentx daemon start
16
+ agentx init # Create config + workspace
17
+ agentx agent add # Add an agent (interactive)
18
+ agentx channel add # Add a channel (Telegram/WhatsApp/Discord/GitLab)
19
+ agentx daemon start # Start
27
20
  ```
28
21
 
29
- That's it. Your agent is live on Telegram.
30
-
31
22
  ## How it works
32
23
 
33
24
  ```
34
25
  Telegram ──┐
35
- WhatsApp ──┤ agentx ┌─ claude -p --cwd /workspace
36
- Discord ───┤ daemon ───┤─ openai API
37
- Cron ──────┤ └─ ollama generate
26
+ WhatsApp ──┤ ┌─ claude -p --cwd /workspace
27
+ Discord ───┤ agentx │
28
+ GitLab ───┤ daemon ────┤─ openai API
29
+ Cron ──────┤ │
30
+ Webhook ───┤ └─ ollama generate
38
31
  A2A mesh ──┘
39
- │
40
- routes messages to the right
41
- agent workspace with wiki context
42
- ```
43
-
44
- Each agent = a workspace directory. For Claude Code agents, permissions, hooks, MCP servers, skills, and memory live in the workspace's `.claude/` directory. AgentX just orchestrates when and where agents run.
45
-
46
- ## CLI Commands
47
-
48
- ### Daemon (core)
49
-
50
- ```bash
51
- agentx daemon start # Start foreground
52
- agentx daemon start --detach # Start background
53
- agentx daemon stop # Stop daemon
54
- agentx daemon status # Show agents, crons, mesh health
55
- agentx daemon logs -f # Follow logs
56
- agentx daemon send <agent> <msg> # Send a task to an agent
57
- agentx daemon send <agent> <msg> --peer server-2 # Send to remote agent
58
- agentx daemon deploy <host> -i ~/.ssh/key --restart # Deploy + restart remote
32
+ │
33
+ Context Engine
34
+ (8 layers, token-budgeted)
59
35
  ```
60
36
 
61
- ### Agents
37
+ Each agent = a workspace directory with Claude Code configuration (`.claude/`, `CLAUDE.md`, skills, hooks, MCP servers). AgentX orchestrates when and where agents run.
62
38
 
63
- ```bash
64
- agentx agent add # Interactive: creates workspace, CLAUDE.md, settings, wiki skill
65
- agentx agent list # List all agents
66
- agentx agent remove <id> # Remove from config (keeps workspace)
67
- ```
39
+ ## Features
68
40
 
69
41
  ### Channels
42
+ - **Telegram** — Multi-account bots, streaming responses, HTML formatting, typing indicators, seen reactions, bot-to-bot delegation, media handling (photos, voice, audio, video, documents)
43
+ - **WhatsApp** — Baileys integration, QR pairing, self-chat mode, per-contact/group agent routing
44
+ - **Discord** — Bot with mention-based routing, DM support
45
+ - **GitLab** — Webhook channel: comments, issues, MRs, pipeline events route to agents. Agents reply as GitLab comments. @mention-based agent resolution in comments.
46
+ - **Webhooks** — Generic `POST /webhook/:agentId` endpoint for Stripe, Sentry, GitHub, etc.
47
+
48
+ ### Core
49
+ - **Multi-agent** — Named agents with custom permissions, concurrency limits, mention-based routing
50
+ - **Context engine** — 8-layer structured context with per-layer token budgets (channel, scope, identity, peers, intent, artifacts, history, wiki)
51
+ - **Wiki knowledge base** — Karpathy/Farzapedia-inspired Markdown wiki with permissions (private/shared/public). Agents compile conversations into articles.
52
+ - **Session continuity** — `--resume SESSION_ID` for Claude Code, conversation history injection for other tiers
53
+ - **Bot-to-bot** — Agents mention each other on Telegram, conversation chains with loop prevention (visited set + max depth)
54
+ - **Group context** — Persistent group conversation log, agents see last 30 messages when mentioned
55
+ - **Media handling** — Photos, voice messages, audio, video, documents downloaded and passed to agent
56
+ - **Reply-to context** — When replying to a message, agent sees the original text
57
+
58
+ ### Operations
59
+ - **Cron scheduler** — Timezone-aware recurring tasks with run logging
60
+ - **A2A mesh** — Cross-machine agent communication over Tailscale/VPN
61
+ - **Rate limiting** — Per-agent, 10/min, 100/hour (configurable)
62
+ - **Token tracking** — Estimated tokens per agent per day, 7-day summaries
63
+ - **Process management** — PID file, graceful shutdown, uncaught exception handlers
64
+ - **72 unit tests** — Config, sessions, wiki, group log, context engine, telegram format
70
65
 
71
- ```bash
72
- agentx channel add # Interactive: Telegram bot token, verify, bind to agent
73
- agentx channel list # List all channel bindings
74
- ```
75
-
76
- **Supported channels:**
77
- - **Telegram** — Multi-account bots, streaming responses, MarkdownV2, typing indicators, seen reactions, bot-to-bot delegation
78
- - **WhatsApp** — Via Baileys (QR pairing), self-chat mode (message yourself to talk to agent), per-contact/group agent routing
79
- - **Discord** — Via discord.js, mention-based routing, DM support
80
-
81
- ### Cron jobs
82
-
83
- ```bash
84
- agentx cron add # Interactive: schedule, agent, prompt, timezone
85
- agentx cron list # List all jobs with status
86
- agentx cron enable <id> # Enable a job
87
- agentx cron disable <id> # Disable a job
88
- ```
89
-
90
- ### Mesh (multi-machine)
91
-
92
- ```bash
93
- agentx mesh add # Interactive: URL, name, verifies connectivity
94
- agentx mesh list # List peers with health status
95
- agentx mesh remove <name> # Remove a peer
96
- ```
97
-
98
- ### Skills
99
-
100
- ```bash
101
- agentx skill add ./path/to/skill --agent my-agent # Add to one agent
102
- agentx skill add ./path/to/skill --all # Add to all agents
103
- agentx skill list # List skills per agent
104
- ```
105
-
106
- ### Hooks
107
-
108
- ```bash
109
- agentx hook add <agent> # Interactive: event, type (command/http), matcher
110
- ```
111
-
112
- ### Migration
66
+ ## CLI Commands
113
67
 
68
+ ### Daemon
114
69
  ```bash
115
- agentx migrate openclaw # Auto-detect ~/.openclaw/
116
- agentx migrate openclaw /path/to/config # Explicit path
117
- agentx migrate openclaw --dry-run # Preview without writing
70
+ agentx daemon start [--detach] # Start (foreground or background)
71
+ agentx daemon stop # Graceful shutdown
72
+ agentx daemon status # Agents, crons, mesh health
73
+ agentx daemon logs [-f] # Tail logs
74
+ agentx daemon send <agent> <msg> # Send task to agent
75
+ agentx daemon send <agent> <msg> --peer server-2 # Remote agent
76
+ agentx daemon deploy <host> -i key [--restart] # Deploy (runs tests first)
118
77
  ```
119
78
 
120
- ### Setup
121
-
79
+ ### Management
122
80
  ```bash
123
- agentx init # Create agentx.json, .env, workspace dirs
124
- agentx init --force # Overwrite existing config
81
+ agentx agent add / list / remove <id>
82
+ agentx channel add / list # Telegram, WhatsApp, Discord, GitLab
83
+ agentx cron add / list / enable / disable <id>
84
+ agentx mesh add / list / remove <name>
85
+ agentx skill add <path> [--agent X] [--all] / list
86
+ agentx hook add <agent>
87
+ agentx config check # Validate config + workspaces
88
+ agentx config show # Print resolved config
89
+ agentx migrate openclaw [path] [--dry-run]
90
+ agentx init [--force]
125
91
  ```
126
92
 
127
93
  ## Configuration
128
94
 
129
- Single `agentx.json` file. Environment variables expanded (`${VAR_NAME}`). Auto-loads `.env`.
95
+ Single `agentx.json`. Environment variables expanded (`${VAR_NAME}`). Auto-loads `.env`.
130
96
 
131
97
  ```jsonc
132
98
  {
133
- "node": {
134
- "id": "my-machine",
135
- "name": "My Machine",
136
- "bind": "127.0.0.1:18800"
137
- },
138
-
139
- "providers": {
140
- "claude": { "apiKey": "${ANTHROPIC_API_KEY}" }
141
- },
99
+ "node": { "id": "my-machine", "name": "My Machine", "bind": "127.0.0.1:18800" },
142
100
 
143
101
  "agents": {
144
102
  "assistant": {
145
103
  "name": "Assistant",
146
104
  "workspace": "/path/to/workspace",
147
- "tier": "claude-code",
105
+ "tier": "claude-code", // "sdk" or "orchestrator"
148
106
  "model": "claude-sonnet-4-6",
149
107
  "mentions": ["@my_bot"],
150
108
  "maxConcurrent": 2,
@@ -162,7 +120,6 @@ Single `agentx.json` file. Environment variables expanded (`${VAR_NAME}`). Auto-
162
120
  },
163
121
  "whatsapp": {
164
122
  "enabled": true,
165
- "sessionDir": ".agentx/whatsapp-sessions",
166
123
  "defaultAgent": "assistant",
167
124
  "routes": [
168
125
  { "contact": "+1234567890", "agent": "assistant" },
@@ -173,6 +130,20 @@ Single `agentx.json` file. Environment variables expanded (`${VAR_NAME}`). Auto-
173
130
  "enabled": true,
174
131
  "token": "${DISCORD_BOT_TOKEN}",
175
132
  "agentBinding": "assistant"
133
+ },
134
+ "gitlab": {
135
+ "enabled": true,
136
+ "host": "https://gitlab.example.com",
137
+ "token": "${GITLAB_TOKEN}",
138
+ "webhookPort": 18810,
139
+ "routes": [
140
+ { "project": "team/project-a", "agent": "pm-a" },
141
+ { "project": "*", "agent": "atlas" }
142
+ ],
143
+ "agentMappings": [
144
+ { "agentId": "coder", "gitlabUsernames": ["coder-bot"], "keywords": ["coder"] },
145
+ { "agentId": "devops", "gitlabUsernames": ["devops-bot"], "keywords": ["deploy"] }
146
+ ]
176
147
  }
177
148
  },
178
149
 
@@ -182,8 +153,7 @@ Single `agentx.json` file. Environment variables expanded (`${VAR_NAME}`). Auto-
182
153
  "schedule": "0 9 * * *",
183
154
  "timezone": "UTC",
184
155
  "agent": "assistant",
185
- "prompt": "Generate today's status report.",
186
- "timeout": 600
156
+ "prompt": "Generate today's status report."
187
157
  }
188
158
  },
189
159
 
@@ -196,115 +166,64 @@ Single `agentx.json` file. Environment variables expanded (`${VAR_NAME}`). Auto-
196
166
  }
197
167
  ```
198
168
 
199
- ## Agent workspace
200
-
201
- Each agent is a directory with Claude Code configuration:
202
-
203
- ```
204
- my-workspace/
205
- ├── .claude/
206
- │ ├── settings.json # Permissions, hooks, env vars
207
- │ ├── .mcp.json # MCP servers
208
- │ ├── agents/ # Subagents
209
- │ └── skills/ # SKILL.md files (gitlab, wiki, etc.)
210
- ├── CLAUDE.md # Agent identity and instructions
211
- └── ... (project files)
212
- ```
213
-
214
- New agents created via `agentx agent add` get `CLAUDE.md`, `settings.json`, and the wiki skill automatically.
215
-
216
- ## Three execution tiers
217
-
218
- | Tier | How | Auth | Best for |
219
- |------|-----|------|----------|
220
- | `claude-code` | Spawns `claude` CLI | Subscription | Full power: subagents, MCP, skills, hooks, 1M context |
221
- | `sdk` | Claude Agent SDK | API key | Programmatic control, headless servers |
222
- | `orchestrator` | AgentX's own loop | Any provider key | Non-Claude providers (OpenAI, Ollama) |
223
-
224
- ## Session continuity
225
-
226
- Agents remember conversations:
227
- - **Claude Code tier**: `--resume SESSION_ID` with reliable ID from `--output-format json`
228
- - **Other tiers**: Recent conversation history injected into each prompt
229
- - **Wiki context**: Relevant knowledge articles injected before each response
169
+ ## Context Engine
230
170
 
231
- ## Wiki knowledge base
171
+ Every agent prompt is built from 8 structured layers, each with a token budget:
232
172
 
233
- Inspired by [Karpathy's LLM knowledge base](https://x.com/karpathy/status/2040572272944324650) and [Farzapedia](https://gist.github.com/farzaa/c35ac0cfbeb957788650e36aabea836d).
173
+ | Layer | Priority | Budget | Content |
174
+ |-------|----------|--------|---------|
175
+ | Channel | 1 | 200 | Channel type + rules (GitLab: no @handles, use GFM) |
176
+ | Scope | 2 | 200 | Group name, project path, or DM |
177
+ | Identity | 3 | 300 | Agent system prompt (first line) |
178
+ | Peers | 4 | 400 | Team roster with handles (Telegram only) |
179
+ | Intent | 5 | 200 | Extracted from message: deploy, review, bugfix... |
180
+ | Artifacts | 6 | 500 | Media, reply-to text, issue/MR references |
181
+ | History | 7 | 1200 | Group conversation or session history |
182
+ | Wiki | 8 | 1000 | Relevant knowledge articles |
234
183
 
235
- Agents build a shared Markdown wiki from conversations. Token-efficient: ~1K tokens for wiki context vs ~10K for session replay.
236
-
237
- ```
238
- .agentx/wiki/
239
- ├── WIKI.md # Master index
240
- ├── raw/entries/ # Auto-ingested conversations
241
- ├── projects/ # Compiled knowledge
242
- ├── decisions/
243
- └── patterns/
244
- ```
245
-
246
- **Permissions**: `private` (owner only), `shared` (listed agents), `public` (all agents).
247
-
248
- ## A2A Mesh
249
-
250
- Run `agentx daemon` on multiple machines. Agents communicate cross-machine via HTTP over Tailscale/VPN.
251
-
252
- ```
253
- MacBook (Nadia, DevOps) ←── Tailscale ──→ Server (Atlas, MTGL, KSI, ...)
254
- :18800 :19900
255
- ```
184
+ Total budget: 4000 tokens. Lower layers truncated if over budget.
256
185
 
257
186
  ## HTTP API
258
187
 
259
- The daemon exposes a REST API:
260
-
261
188
  | Endpoint | Method | Description |
262
189
  |----------|--------|-------------|
263
- | `/health` | GET | System status, agents, crons, mesh |
190
+ | `/health` | GET | Status, agents, crons, mesh, today's usage |
264
191
  | `/agents` | GET | List agents |
265
192
  | `/crons` | GET | List cron jobs |
266
- | `/mesh` | GET | Mesh peer directory |
193
+ | `/mesh` | GET | Mesh peers |
194
+ | `/usage` | GET | 7-day token usage per agent |
267
195
  | `/task` | POST | `{ "agent": "id", "message": "..." }` |
268
196
  | `/mesh/task` | POST | `{ "peer": "name", "message": "..." }` |
197
+ | `/webhook/:agentId[/:source]` | POST | Webhook callback (GitLab, GitHub, Stripe, Sentry) |
269
198
  | `/.well-known/agent-card.json` | GET | A2A agent discovery |
270
199
 
200
+ ## Three execution tiers
201
+
202
+ | Tier | How | Auth | Best for |
203
+ |------|-----|------|----------|
204
+ | `claude-code` | Spawns `claude` CLI | Subscription | Full power: subagents, MCP, skills, hooks, 1M context |
205
+ | `sdk` | Claude Agent SDK | API key | Programmatic control, headless servers |
206
+ | `orchestrator` | AgentX's own loop | Any provider key | Non-Claude providers (OpenAI, Ollama) |
207
+
271
208
  ## Migrating from OpenClaw
272
209
 
273
210
  ```bash
274
- agentx migrate openclaw
211
+ agentx migrate openclaw # Auto-imports agents, channels, crons, skills
275
212
  ```
276
213
 
277
- Auto-imports agents, Telegram bots, cron jobs, and WhatsApp config. Also ports:
278
- - Skills to workspace `.claude/skills/`
279
- - Permissions to `.claude/settings.json`
280
- - Agent identity to `CLAUDE.md`
281
- - WhatsApp sessions (reuses existing pairing)
282
-
283
- | OpenClaw | AgentX |
284
- |----------|--------|
285
- | Gateway + Node | Single daemon per machine |
286
- | OAuth proxy | Direct API key or subscription |
287
- | `openclaw.json` | `agentx.json` |
288
- | `exec-approvals.json` | `.claude/settings.json` per workspace |
289
-
290
214
  ## Use cases
291
215
 
292
- - **Team of Telegram bots** — each project gets its own bot + agent with isolated workspace
216
+ - **Team of Telegram bots** — each project gets its own bot + agent
217
+ - **GitLab code review** — comment on MR, agent reviews and replies as a GitLab comment
293
218
  - **WhatsApp assistant** — message yourself, agent replies in self-chat
294
219
  - **Scheduled content** — cron jobs generate blog posts, reports, social media drafts
295
220
  - **Multi-machine swarm** — agents on MacBook + server collaborate via mesh
296
- - **Bot-to-bot delegation** — Nadia mentions @devops in her response, DevOps agent picks up
297
- - **Wiki knowledge** — agents accumulate knowledge, share insights across the team
221
+ - **Webhook automation** — Sentry error → DevOps agent investigates, Stripe payment → billing agent processes
222
+ - **Bot-to-bot delegation** — Nadia mentions @devops, DevOps picks up and responds
298
223
 
299
224
  ## Legal
300
225
 
301
- AgentX is a **self-hosted, bring-your-own-key** tool:
302
-
303
- - Each user provides their own API key or Claude subscription
304
- - No credentials are stored, shared, or proxied by AgentX
305
- - Built on official public packages: Claude API, Claude Agent SDK, Claude Code CLI
306
- - Provider-agnostic — works with any LLM, not locked to Anthropic
307
- - Same model as LangChain, CrewAI, AutoGen, Dify, n8n
226
+ Self-hosted, bring-your-own-key. No credentials stored or proxied. Built on official public packages (Claude API, Claude Agent SDK, Claude Code CLI). Same model as LangChain, CrewAI, AutoGen.
308
227
 
309
228
  ## License
310
229
 
@@ -0,0 +1,2 @@
1
+ import{s as a,t as b,u as c}from"./chunk-F73GPYCO.js";import"./chunk-Z4GC5D6D.js";import"./chunk-FRFR27IN.js";import"./chunk-SFQUP3BP.js";import"./chunk-MGMZNJCE.js";import"./chunk-M7HKBG3V.js";import"./chunk-4YCH6IZV.js";export{a as createAgentContext,b as generate,c as generateStream};
2
+ //# sourceMappingURL=agent-K2YOEOJ5.js.map
@@ -0,0 +1,2 @@
1
+ var d=Object.defineProperty;var e=(a,b,c)=>b in a?d(a,b,{enumerable:!0,configurable:!0,writable:!0,value:c}):a[b]=c;var f=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+a+'" is not supported')});var g=(a,b,c)=>(e(a,typeof b!="symbol"?b+"":b,c),c);export{f as a,g as b};
2
+ //# sourceMappingURL=chunk-4YCH6IZV.js.map
@@ -1,4 +1,4 @@
1
- import{d as X,g as v,k as c}from"./chunk-PCAYW54Q.js";import{a as Ce,d as fe}from"./chunk-FRFR27IN.js";import{a as _e,b as Pe,c as ge}from"./chunk-SFQUP3BP.js";import{a as de,c as ue,g as me}from"./chunk-MGMZNJCE.js";import{a as F,b as ce,f as pe}from"./chunk-M7HKBG3V.js";import{z as R}from"zod";var Se=R.object({provider:R.enum(["claude-code","claude","openai","ollama","custom"]).default("claude-code"),model:R.string().optional(),apiKey:R.string().optional(),skills:R.array(R.string()).default([]),output:R.object({dir:R.string().default("./generated")}).default({}),context7:R.object({enabled:R.boolean().default(!0),apiKey:R.string().optional()}).default({}),agentic:R.object({maxIterations:R.number().default(20),enabledTools:R.array(R.string()).default(["create_files","ask_user","read_file","search_files","list_directory","run_command","edit_file"]),disabledTools:R.array(R.string()).default([])}).default({})}),pt=["component","page","api","website","document","script","config","skill","media","report","test","workflow","schema","email","diagram","auto"],dt={component:"UI component (any framework)",page:"Full page or screen",api:"API endpoint, route handler, or service",website:"Multi-page website or app",document:"Markdown, documentation, or specification",script:"Standalone script or utility",config:"Configuration file or setup",skill:"Agent skill (SKILL.md format for skills.sh)",media:"Media generation prompt (image/audio/video description)",report:"Analysis report or audit",test:"Test suite, test fixtures, or test data",workflow:"CI/CD pipeline, GitHub Actions, or automation",schema:"Database schema, Zod validators, or GraphQL types",email:"Email template (React Email, MJML, HTML)",diagram:"Mermaid, D2, or PlantUML diagram",auto:"Auto-detect the best output type"};import{existsSync as He,promises as Ke}from"fs";import q from"path";import Ye from"fast-glob";var Te={"prisma/schema.prisma":{type:"prisma",category:"database"},"drizzle/schema.ts":{type:"drizzle",category:"database"},"schema.graphql":{type:"graphql",category:"api"},"schema.gql":{type:"graphql",category:"api"},"openapi.yaml":{type:"openapi",category:"api"},"openapi.json":{type:"openapi",category:"api"},"swagger.yaml":{type:"openapi",category:"api"},"swagger.json":{type:"openapi",category:"api"}};async function Re(o){let e={},t=await Ye.glob("**/*",{cwd:o,deep:4,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/target/**","**/__pycache__/**","**/vendor/**","**/.git/**"],onlyFiles:!0});for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="database"){let a=await K(q.resolve(o,l));if(a){e.database={type:i.type,content:Z(a,3e3),tables:Je(a,i.type)};break}}}for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="api"){let a=await K(q.resolve(o,l));if(a){e.api={type:i.type,content:Z(a,3e3)};break}}}if(!e.api){let s=t.find(i=>i.includes("trpc")&&(i.endsWith("router.ts")||i.endsWith("router.js")));if(s){let i=await K(q.resolve(o,s));i&&(e.api={type:"trpc",content:Z(i,3e3)})}}let n=t.find(s=>s===".env.example"||s===".env.local.example"||s===".env.template");if(n){let s=await K(q.resolve(o,n));s&&(e.env=Qe(s))}let r=t.filter(s=>(s.includes("models")||s.includes("types")||s.includes("schemas"))&&(s.endsWith(".ts")||s.endsWith(".py")||s.endsWith(".rs")||s.endsWith(".go")));if(r.length){e.models=[];for(let s of r.slice(0,5)){let i=await K(q.resolve(o,s));i&&e.models.push({path:s,content:Z(i,2e3),type:q.extname(s).slice(1)})}}return e}function Je(o,e){if(e==="prisma"){let t=o.match(/model\s+(\w+)\s*\{/g);return t?t.map(n=>n.replace(/model\s+/,"").replace(/\s*\{/,"")):[]}return[]}function Qe(o){return{variables:o.split(`
1
+ import{d as X,g as v,k as c}from"./chunk-Z4GC5D6D.js";import{a as Ce,d as fe}from"./chunk-FRFR27IN.js";import{a as _e,b as Pe,c as ge}from"./chunk-SFQUP3BP.js";import{a as de,c as ue,g as me}from"./chunk-MGMZNJCE.js";import{a as F,b as ce,f as pe}from"./chunk-M7HKBG3V.js";import{z as R}from"zod";var Se=R.object({provider:R.enum(["claude-code","claude","openai","ollama","custom"]).default("claude-code"),model:R.string().optional(),apiKey:R.string().optional(),skills:R.array(R.string()).default([]),output:R.object({dir:R.string().default("./generated")}).default({}),context7:R.object({enabled:R.boolean().default(!0),apiKey:R.string().optional()}).default({}),agentic:R.object({maxIterations:R.number().default(20),enabledTools:R.array(R.string()).default(["create_files","ask_user","read_file","search_files","list_directory","run_command","edit_file"]),disabledTools:R.array(R.string()).default([])}).default({})}),pt=["component","page","api","website","document","script","config","skill","media","report","test","workflow","schema","email","diagram","auto"],dt={component:"UI component (any framework)",page:"Full page or screen",api:"API endpoint, route handler, or service",website:"Multi-page website or app",document:"Markdown, documentation, or specification",script:"Standalone script or utility",config:"Configuration file or setup",skill:"Agent skill (SKILL.md format for skills.sh)",media:"Media generation prompt (image/audio/video description)",report:"Analysis report or audit",test:"Test suite, test fixtures, or test data",workflow:"CI/CD pipeline, GitHub Actions, or automation",schema:"Database schema, Zod validators, or GraphQL types",email:"Email template (React Email, MJML, HTML)",diagram:"Mermaid, D2, or PlantUML diagram",auto:"Auto-detect the best output type"};import{existsSync as He,promises as Ke}from"fs";import q from"path";import Ye from"fast-glob";var Te={"prisma/schema.prisma":{type:"prisma",category:"database"},"drizzle/schema.ts":{type:"drizzle",category:"database"},"schema.graphql":{type:"graphql",category:"api"},"schema.gql":{type:"graphql",category:"api"},"openapi.yaml":{type:"openapi",category:"api"},"openapi.json":{type:"openapi",category:"api"},"swagger.yaml":{type:"openapi",category:"api"},"swagger.json":{type:"openapi",category:"api"}};async function Re(o){let e={},t=await Ye.glob("**/*",{cwd:o,deep:4,ignore:["**/node_modules/**","**/dist/**","**/build/**","**/.next/**","**/target/**","**/__pycache__/**","**/vendor/**","**/.git/**"],onlyFiles:!0});for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="database"){let a=await K(q.resolve(o,l));if(a){e.database={type:i.type,content:Z(a,3e3),tables:Je(a,i.type)};break}}}for(let[s,i]of Object.entries(Te)){let l=t.find(a=>a.endsWith(s)||a===s);if(l&&i.category==="api"){let a=await K(q.resolve(o,l));if(a){e.api={type:i.type,content:Z(a,3e3)};break}}}if(!e.api){let s=t.find(i=>i.includes("trpc")&&(i.endsWith("router.ts")||i.endsWith("router.js")));if(s){let i=await K(q.resolve(o,s));i&&(e.api={type:"trpc",content:Z(i,3e3)})}}let n=t.find(s=>s===".env.example"||s===".env.local.example"||s===".env.template");if(n){let s=await K(q.resolve(o,n));s&&(e.env=Qe(s))}let r=t.filter(s=>(s.includes("models")||s.includes("types")||s.includes("schemas"))&&(s.endsWith(".ts")||s.endsWith(".py")||s.endsWith(".rs")||s.endsWith(".go")));if(r.length){e.models=[];for(let s of r.slice(0,5)){let i=await K(q.resolve(o,s));i&&e.models.push({path:s,content:Z(i,2e3),type:q.extname(s).slice(1)})}}return e}function Je(o,e){if(e==="prisma"){let t=o.match(/model\s+(\w+)\s*\{/g);return t?t.map(n=>n.replace(/model\s+/,"").replace(/\s*\{/,"")):[]}return[]}function Qe(o){return{variables:o.split(`
2
2
  `).filter(n=>n.trim()&&!n.trim().startsWith("#")).map(n=>{let[r]=n.split("="),s=r.trim(),i=n.includes("=")&&n.split("=")[1]?.trim().length>0;return{key:s,required:!i}})}}async function K(o){try{return He(o)?await Ke.readFile(o,"utf8"):null}catch{return null}}function Z(o,e){return o.length<=e?o:o.slice(0,e)+`
3
3
  ... (truncated)`}function Ae(o){let e=[];if(o.database&&e.push(`## Database Schema (${o.database.type})
4
4
  `+(o.database.tables?.length?`Tables: ${o.database.tables.join(", ")}
@@ -45,7 +45,7 @@ Options: ${n.join(", ")}`),{tool_use_id:e.id,content:"Question sent to user.",fo
45
45
  `);l.push({role:"assistant",content:w.content+(G?`
46
46
 
47
47
  Files created:
48
- ${G}`:"")}),l.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}return{files:a,content:p,followUp:g,tokensUsed:x,iterations:b}}function ke(o){return typeof o.generateRaw=="function"}var se=class{queue=[];resolvers=[];closed=!1;push(e){if(this.closed)return;let t=this.resolvers.shift();if(t){t({value:e,done:!1});return}this.queue.push(e)}close(){if(!this.closed){this.closed=!0;for(let e of this.resolvers.splice(0))e({value:void 0,done:!0})}}async next(){return this.queue.length?{value:this.queue.shift(),done:!1}:this.closed?{value:void 0,done:!0}:new Promise(e=>{this.resolvers.push(e)})}async*[Symbol.asyncIterator](){for(;;){let{value:e,done:t}=await this.next();if(t)return;yield e}}};async function qe(o,e,t){let n=Se.parse(t||{}),r=new Y(o);await r.load();let[s,i,l]=await Promise.all([_e(o),Re(o),Ce(o)]),a="";if(n.context7.enabled)try{a=await $e(s,e,n.context7.apiKey)}catch{}let x=r.buildMemoryContext(e),p=be(o);return v.context("memory",x?"loaded":"empty"),v.context("instructions",p?"loaded from project":"none"),{techStack:s,schemas:i,skills:l,docs:a,config:n,memoryContext:x,projectInstructions:p}}async function Ro(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let u=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:prompt hook");u.modified?.task&&(p=String(u.modified.task))}if(c.has("pre:generate")){let u=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:generate hook")}F.info("Analyzing project...");let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);F.info(`Output type: ${b}`);let w=fe(g.skills,p,b);w.length&&F.info(`Loaded ${w.length} relevant skill(s): ${w.map(u=>u.skill.frontmatter.name).join(", ")}`);let $=Be(g,b,w.map(u=>u.skill));if(!await pe(l))throw new Error("No credentials configured. Run `agentx model` to set up.");let C=me(s,l),S=i||ce()?.model,O=[...o.sessionMessages||[],{role:"user",content:p}];F.info("Generating...");let M=ke(C),k=o.maxSteps??(M?20:5),h=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...O],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:k,enabledTools:g.config.agentic.enabledTools.filter(u=>!g.config.agentic.disabledTools.includes(u)),interactive:x,overwrite:n,dryRun:r,onProgress:u=>{u.type==="iteration_start"&&u.iteration>1&&F.info(`Step ${u.iteration}/${k}...`),u.type==="tool_call"&&v.step(0,`Tool: ${u.name}`)}});if(h.tokensUsed){let u=S||"claude-sonnet-4-20250514",L=Math.round(h.tokensUsed*.3),ie=h.tokensUsed-L;X.recordStep(1,u,L,ie)}let{content:j}=h,{followUp:_,tokensUsed:y}=h;if(h.iterations>1&&F.info(`Completed in ${h.iterations} step(s)`),c.has("post:response")){let u=await c.execute("post:response",{event:"post:response",content:j,task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by post:response hook");u.modified?.content&&(j=String(u.modified.content))}if(_&&x)return{files:{written:[],skipped:[],errors:[]},content:j,outputType:b,followUp:_,tokensUsed:y};let U=new Map;for(let u of h.files)U.set(u.path,u);let A=ne(b,g.techStack,o.outputDir),T=await oe(Array.from(U.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:A}),I;if(o.heal!==!1&&!r&&T.written.length>0){let{HealEngine:u}=await import("./heal-RDZZJXDZ.js");I=await new u(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(T.written,p),!I.healed&&I.error&&await c.execute("on:error",{event:"on:error",error:new Error(I.error),task:p,cwd:t})}return c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:j,cwd:t}),{files:T,content:j,outputType:b,tokensUsed:y,healResult:I}}async function*Ao(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let d=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:prompt hook"};return}d.modified?.task&&(p=String(d.modified.task))}if(c.has("pre:generate")){let d=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:generate hook"};return}}let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);yield{type:"context_ready",outputType:b};let w=fe(g.skills,p,b),$=Be(g,b,w.map(d=>d.skill));if(!await pe(l)){yield{type:"error",error:"No credentials configured. Run `agentx model` to set up."};return}let C=me(s,l),S=i||ce()?.model,O=ke(C),M=o.maxSteps??(O?20:5),k=[...o.sessionMessages||[],{role:"user",content:p}];if(O){let d=new se,P,f,W=(async()=>{try{P=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...k],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:M,enabledTools:g.config.agentic.enabledTools.filter(m=>!g.config.agentic.disabledTools.includes(m)),interactive:x,overwrite:n,dryRun:r,onProgress:m=>{m.type==="text_delta"&&d.push({type:"text_delta",text:m.text}),m.type==="iteration_start"&&d.push({type:"iteration",iteration:m.iteration}),m.type==="tool_call"&&d.push({type:"tool_call",name:m.name,id:m.id}),m.type==="tool_result"&&d.push({type:"tool_result",name:m.name,id:m.id,is_error:m.is_error}),m.type==="files_created"&&d.push({type:"step_complete",step:0,filesCount:m.files.length})}})}catch(m){f=m}finally{d.close()}})();for await(let m of d)yield m;if(await W,f){yield{type:"error",error:f instanceof Error?f.message:String(f)};return}if(!P){yield{type:"error",error:"Agentic loop failed without a result"};return}yield{type:"done",result:{content:P.content,files:P.files,tokensUsed:P.tokensUsed,followUp:P.followUp}};let{content:E}=P;if(c.has("post:response")){let m=await c.execute("post:response",{event:"post:response",content:E,task:p,cwd:t});if(m.blocked){yield{type:"error",error:m.message||"Blocked by post:response hook"};return}m.modified?.content&&(E=String(m.modified.content))}if(P.followUp&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:E,outputType:b,followUp:P.followUp,tokensUsed:P.tokensUsed}};return}let z=new Map;for(let m of P.files)z.set(m.path,m);let le=ne(b,g.techStack,o.outputDir),V=await oe(Array.from(z.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:le}),H;if(o.heal!==!1&&!r&&V.written.length>0){let{HealEngine:m}=await import("./heal-RDZZJXDZ.js");H=await new m(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(V.written,p)}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:E,cwd:t}),yield{type:"generate_result",result:{files:V,content:E,outputType:b,tokensUsed:P.tokensUsed,healResult:H}};return}let h=[{role:"system",content:$},...k],j=[],_=0,y="",U,A=0;A++,v.step(A,`Starting generation (model: ${S||"default"})`);let T;if(C.stream){let d="",P;for await(let f of C.stream(h,{model:S,maxTokens:8192}))yield f,f.type==="text_delta"&&(d+=f.text),f.type==="done"&&(P=f.result);T=P||{content:d,files:[],tokensUsed:0}}else{let d=await C.generate(h,{model:S,maxTokens:8192});d.content&&(yield{type:"text_delta",text:d.content}),yield{type:"done",result:d},T=d}_+=T.tokensUsed||0,y=T.content;let I=T.tokensUsed||0,u=S||"claude-sonnet-4-20250514",L=Math.round(I*.3),ie=I-L;if(X.recordStep(A,u,L,ie),v.api("generate",u,I),v.step(A,`Generated ${T.files.length} file(s), ${I} tokens`),T.files.length&&j.push(...T.files),T.followUp&&(U=T.followUp),yield{type:"step_complete",step:A,filesCount:T.files.length},!U&&(y.includes("[CONTINUE]")||y.includes("Next, I'll")||y.includes("Now let me")||y.includes("I'll also generate"))&&T.files.length>0){let P=T.files.map(f=>`Created: ${f.path}${f.description?` \u2014 ${f.description}`:""}`).join(`
48
+ ${G}`:"")}),l.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}return{files:a,content:p,followUp:g,tokensUsed:x,iterations:b}}function ke(o){return typeof o.generateRaw=="function"}var se=class{queue=[];resolvers=[];closed=!1;push(e){if(this.closed)return;let t=this.resolvers.shift();if(t){t({value:e,done:!1});return}this.queue.push(e)}close(){if(!this.closed){this.closed=!0;for(let e of this.resolvers.splice(0))e({value:void 0,done:!0})}}async next(){return this.queue.length?{value:this.queue.shift(),done:!1}:this.closed?{value:void 0,done:!0}:new Promise(e=>{this.resolvers.push(e)})}async*[Symbol.asyncIterator](){for(;;){let{value:e,done:t}=await this.next();if(t)return;yield e}}};async function qe(o,e,t){let n=Se.parse(t||{}),r=new Y(o);await r.load();let[s,i,l]=await Promise.all([_e(o),Re(o),Ce(o)]),a="";if(n.context7.enabled)try{a=await $e(s,e,n.context7.apiKey)}catch{}let x=r.buildMemoryContext(e),p=be(o);return v.context("memory",x?"loaded":"empty"),v.context("instructions",p?"loaded from project":"none"),{techStack:s,schemas:i,skills:l,docs:a,config:n,memoryContext:x,projectInstructions:p}}async function Ro(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let u=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:prompt hook");u.modified?.task&&(p=String(u.modified.task))}if(c.has("pre:generate")){let u=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by pre:generate hook")}F.info("Analyzing project...");let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);F.info(`Output type: ${b}`);let w=fe(g.skills,p,b);w.length&&F.info(`Loaded ${w.length} relevant skill(s): ${w.map(u=>u.skill.frontmatter.name).join(", ")}`);let $=Be(g,b,w.map(u=>u.skill));if(!await pe(l))throw new Error("No credentials configured. Run `agentx model` to set up.");let C=me(s,l),S=i||ce()?.model,O=[...o.sessionMessages||[],{role:"user",content:p}];F.info("Generating...");let M=ke(C),k=o.maxSteps??(M?20:5),h=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...O],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:k,enabledTools:g.config.agentic.enabledTools.filter(u=>!g.config.agentic.disabledTools.includes(u)),interactive:x,overwrite:n,dryRun:r,onProgress:u=>{u.type==="iteration_start"&&u.iteration>1&&F.info(`Step ${u.iteration}/${k}...`),u.type==="tool_call"&&v.step(0,`Tool: ${u.name}`)}});if(h.tokensUsed){let u=S||"claude-sonnet-4-20250514",L=Math.round(h.tokensUsed*.3),ie=h.tokensUsed-L;X.recordStep(1,u,L,ie)}let{content:j}=h,{followUp:_,tokensUsed:y}=h;if(h.iterations>1&&F.info(`Completed in ${h.iterations} step(s)`),c.has("post:response")){let u=await c.execute("post:response",{event:"post:response",content:j,task:p,cwd:t});if(u.blocked)throw new Error(u.message||"Blocked by post:response hook");u.modified?.content&&(j=String(u.modified.content))}if(_&&x)return{files:{written:[],skipped:[],errors:[]},content:j,outputType:b,followUp:_,tokensUsed:y};let U=new Map;for(let u of h.files)U.set(u.path,u);let A=ne(b,g.techStack,o.outputDir),T=await oe(Array.from(U.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:A}),I;if(o.heal!==!1&&!r&&T.written.length>0){let{HealEngine:u}=await import("./heal-UV5A6B5T.js");I=await new u(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(T.written,p),!I.healed&&I.error&&await c.execute("on:error",{event:"on:error",error:new Error(I.error),task:p,cwd:t})}return c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:j,cwd:t}),{files:T,content:j,outputType:b,tokensUsed:y,healResult:I}}async function*Ao(o){let{task:e,cwd:t,overwrite:n=!1,dryRun:r=!1,provider:s="claude-code",model:i,apiKey:l,context7:a=!0,interactive:x=!0}=o,p=e;if(c.has("pre:prompt")){let d=await c.execute("pre:prompt",{event:"pre:prompt",task:e,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:prompt hook"};return}d.modified?.task&&(p=String(d.modified.task))}if(c.has("pre:generate")){let d=await c.execute("pre:generate",{event:"pre:generate",task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by pre:generate hook"};return}}let g=await qe(t,p,{provider:s,context7:{enabled:a,apiKey:l}}),b=he(o.outputType,p);yield{type:"context_ready",outputType:b};let w=fe(g.skills,p,b),$=Be(g,b,w.map(d=>d.skill));if(!await pe(l)){yield{type:"error",error:"No credentials configured. Run `agentx model` to set up."};return}let C=me(s,l),S=i||ce()?.model,O=ke(C),M=o.maxSteps??(O?20:5),k=[...o.sessionMessages||[],{role:"user",content:p}];if(O){let d=new se,P,f,W=(async()=>{try{P=await xe({provider:C,systemPrompt:$,messages:[{role:"system",content:$},...k],providerOptions:{model:S,maxTokens:8192},cwd:t,maxIterations:M,enabledTools:g.config.agentic.enabledTools.filter(m=>!g.config.agentic.disabledTools.includes(m)),interactive:x,overwrite:n,dryRun:r,onProgress:m=>{m.type==="text_delta"&&d.push({type:"text_delta",text:m.text}),m.type==="iteration_start"&&d.push({type:"iteration",iteration:m.iteration}),m.type==="tool_call"&&d.push({type:"tool_call",name:m.name,id:m.id}),m.type==="tool_result"&&d.push({type:"tool_result",name:m.name,id:m.id,is_error:m.is_error}),m.type==="files_created"&&d.push({type:"step_complete",step:0,filesCount:m.files.length})}})}catch(m){f=m}finally{d.close()}})();for await(let m of d)yield m;if(await W,f){yield{type:"error",error:f instanceof Error?f.message:String(f)};return}if(!P){yield{type:"error",error:"Agentic loop failed without a result"};return}yield{type:"done",result:{content:P.content,files:P.files,tokensUsed:P.tokensUsed,followUp:P.followUp}};let{content:E}=P;if(c.has("post:response")){let m=await c.execute("post:response",{event:"post:response",content:E,task:p,cwd:t});if(m.blocked){yield{type:"error",error:m.message||"Blocked by post:response hook"};return}m.modified?.content&&(E=String(m.modified.content))}if(P.followUp&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:E,outputType:b,followUp:P.followUp,tokensUsed:P.tokensUsed}};return}let z=new Map;for(let m of P.files)z.set(m.path,m);let le=ne(b,g.techStack,o.outputDir),V=await oe(Array.from(z.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:le}),H;if(o.heal!==!1&&!r&&V.written.length>0){let{HealEngine:m}=await import("./heal-UV5A6B5T.js");H=await new m(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(V.written,p)}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:E,cwd:t}),yield{type:"generate_result",result:{files:V,content:E,outputType:b,tokensUsed:P.tokensUsed,healResult:H}};return}let h=[{role:"system",content:$},...k],j=[],_=0,y="",U,A=0;A++,v.step(A,`Starting generation (model: ${S||"default"})`);let T;if(C.stream){let d="",P;for await(let f of C.stream(h,{model:S,maxTokens:8192}))yield f,f.type==="text_delta"&&(d+=f.text),f.type==="done"&&(P=f.result);T=P||{content:d,files:[],tokensUsed:0}}else{let d=await C.generate(h,{model:S,maxTokens:8192});d.content&&(yield{type:"text_delta",text:d.content}),yield{type:"done",result:d},T=d}_+=T.tokensUsed||0,y=T.content;let I=T.tokensUsed||0,u=S||"claude-sonnet-4-20250514",L=Math.round(I*.3),ie=I-L;if(X.recordStep(A,u,L,ie),v.api("generate",u,I),v.step(A,`Generated ${T.files.length} file(s), ${I} tokens`),T.files.length&&j.push(...T.files),T.followUp&&(U=T.followUp),yield{type:"step_complete",step:A,filesCount:T.files.length},!U&&(y.includes("[CONTINUE]")||y.includes("Next, I'll")||y.includes("Now let me")||y.includes("I'll also generate"))&&T.files.length>0){let P=T.files.map(f=>`Created: ${f.path}${f.description?` \u2014 ${f.description}`:""}`).join(`
49
49
  `);for(h.push({role:"assistant",content:y+(P?`
50
50
 
51
51
  Files created:
@@ -53,7 +53,7 @@ ${P}`:"")}),h.push({role:"user",content:"Continue generating the remaining files
53
53
  `);h.push({role:"assistant",content:f.content+(H?`
54
54
 
55
55
  Files created:
56
- ${H}`:"")}),h.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}}if(c.has("post:response")){let d=await c.execute("post:response",{event:"post:response",content:y,task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by post:response hook"};return}d.modified?.content&&(y=String(d.modified.content))}if(U&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:y,outputType:b,followUp:U,tokensUsed:_}};return}let ve=new Map;for(let d of j)ve.set(d.path,d);let ze=ne(b,g.techStack,o.outputDir),ae=await oe(Array.from(ve.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:ze}),B;if(o.heal!==!1&&!r&&ae.written.length>0){let{HealEngine:d}=await import("./heal-RDZZJXDZ.js");B=await new d(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(ae.written,p),!B.healed&&B.error&&await c.execute("on:error",{event:"on:error",error:new Error(B.error),task:p,cwd:t})}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:y,cwd:t}),yield{type:"generate_result",result:{files:ae,content:y,outputType:b,tokensUsed:_,healResult:B}}}function Be(o,e,t){let n=[];n.push(`You are agentx, an agentic code generation tool. You generate high-quality, production-ready output for any tech stack.
56
+ ${H}`:"")}),h.push({role:"user",content:"Continue generating the remaining files. Build on what you've already created. When finished, do not include [CONTINUE] in your response."})}}if(c.has("post:response")){let d=await c.execute("post:response",{event:"post:response",content:y,task:p,cwd:t});if(d.blocked){yield{type:"error",error:d.message||"Blocked by post:response hook"};return}d.modified?.content&&(y=String(d.modified.content))}if(U&&x){yield{type:"generate_result",result:{files:{written:[],skipped:[],errors:[]},content:y,outputType:b,followUp:U,tokensUsed:_}};return}let ve=new Map;for(let d of j)ve.set(d.path,d);let ze=ne(b,g.techStack,o.outputDir),ae=await oe(Array.from(ve.values()),{cwd:t,overwrite:n,dryRun:r,outputDir:ze}),B;if(o.heal!==!1&&!r&&ae.written.length>0){let{HealEngine:d}=await import("./heal-UV5A6B5T.js");B=await new d(t,{enabled:!0,testCommand:o.healConfig?.testCommand,buildCommand:o.healConfig?.buildCommand,lintCommand:o.healConfig?.lintCommand,maxAttempts:o.healConfig?.maxAttempts??3,provider:s,model:S,apiKey:l}).detectAndHeal(ae.written,p),!B.healed&&B.error&&await c.execute("on:error",{event:"on:error",error:new Error(B.error),task:p,cwd:t})}c.has("post:generate")&&await c.execute("post:generate",{event:"post:generate",task:p,content:y,cwd:t}),yield{type:"generate_result",result:{files:ae,content:y,outputType:b,tokensUsed:_,healResult:B}}}function Be(o,e,t){let n=[];n.push(`You are agentx, an agentic code generation tool. You generate high-quality, production-ready output for any tech stack.
57
57
 
58
58
  Your primary tool is \`create_files\` \u2014 use it to output all generated code, documents, and configs as files.
59
59
  If the request is ambiguous or you need critical information to proceed correctly, use \`ask_user\` to ask a clarifying question.
@@ -103,4 +103,4 @@ ${o.projectInstructions}`),o.memoryContext&&n.push(o.memoryContext),n.push(`# Ou
103
103
  Generate output appropriate for: ${e}. Use the \`create_files\` tool to output all files.`),n.join(`
104
104
 
105
105
  `)}export{Se as a,pt as b,dt as c,Re as d,Ae as e,$e as f,Ie as g,he as h,Oe as i,Ue as j,ye as k,ee as l,N as m,Y as n,Ne as o,be as p,we as q,Q as r,qe as s,Ro as t,Ao as u};
106
- //# sourceMappingURL=chunk-KVWUPUR5.js.map
106
+ //# sourceMappingURL=chunk-F73GPYCO.js.map