cawdex 1.35.65 → 1.35.67

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 (59) hide show
  1. package/README.md +186 -186
  2. package/bin/anycode.js +2 -2
  3. package/bin/cawdex.js +408 -408
  4. package/bin/ecc-hooks.cjs +11 -11
  5. package/dist/agents.js +1424 -1424
  6. package/dist/autonomous-loops.js +287 -287
  7. package/dist/command-palette.js +1 -1
  8. package/dist/command-palette.js.map +1 -1
  9. package/dist/compaction.js +8 -8
  10. package/dist/content-engine.js +543 -543
  11. package/dist/coverage.js +39 -39
  12. package/dist/docs-sync.js +98 -98
  13. package/dist/evaluation.js +452 -452
  14. package/dist/git-workflow.js +49 -49
  15. package/dist/index.js +75 -46
  16. package/dist/index.js.map +1 -1
  17. package/dist/instant-answer.js +10 -0
  18. package/dist/instant-answer.js.map +1 -1
  19. package/dist/modes.js +355 -355
  20. package/dist/orchestration.js +15 -15
  21. package/dist/pm2-manager.js +26 -26
  22. package/dist/prompt-buffer.d.ts +7 -0
  23. package/dist/prompt-buffer.js +31 -0
  24. package/dist/prompt-buffer.js.map +1 -1
  25. package/dist/query.d.ts +4 -0
  26. package/dist/query.js +79 -64
  27. package/dist/query.js.map +1 -1
  28. package/dist/refactor.js +87 -87
  29. package/dist/search-first.js +92 -92
  30. package/dist/session-picker.d.ts +44 -0
  31. package/dist/session-picker.js +227 -0
  32. package/dist/session-picker.js.map +1 -0
  33. package/dist/skill-create.js +100 -100
  34. package/dist/stitch.js +1 -1
  35. package/dist/swarm.d.ts +34 -54
  36. package/dist/swarm.js +175 -63
  37. package/dist/swarm.js.map +1 -1
  38. package/dist/system-prompt.js +10 -10
  39. package/dist/verification.js +55 -55
  40. package/dist/walkthrough.js +5 -5
  41. package/package.json +1 -1
  42. package/resources/__init__.py +1 -1
  43. package/resources/exgentic/cawdex_agent/README.md +114 -114
  44. package/resources/exgentic/cawdex_agent/__init__.py +5 -5
  45. package/resources/exgentic/cawdex_agent/agent.py +605 -605
  46. package/resources/exgentic/cawdex_agent/requirements.txt +2 -2
  47. package/resources/exgentic/cawdex_agent/setup.sh +21 -21
  48. package/resources/exgentic/cawdex_agent/utils.py +1061 -1061
  49. package/resources/hal/cawdex_agent/README.md +24 -24
  50. package/resources/hal/cawdex_agent/__init__.py +1 -1
  51. package/resources/hal/cawdex_agent/main.py +550 -550
  52. package/resources/hal/cawdex_agent/requirements.txt +2 -2
  53. package/resources/kbench/cawdex_agent/README.md +107 -107
  54. package/resources/kbench/cawdex_agent/adapter.manifest.json +19 -19
  55. package/resources/kbench/cawdex_agent/runner.mjs +753 -753
  56. package/resources/open_agent_leaderboard/cawdex-agent-card.md +119 -119
  57. package/resources/terminal_bench/__init__.py +1 -1
  58. package/resources/terminal_bench/cawdex_agent.py +174 -174
  59. package/resources/terminal_bench/setup.sh +121 -121
@@ -65,34 +65,34 @@ export function buildCommitPrompt(cwd) {
65
65
  const recentLog = gitLog(cwd, 5);
66
66
  if (!status && !stagedDiff && !unstagedDiff)
67
67
  return null;
68
- return `Generate a git commit for the following changes.
69
-
70
- ## Git Status
71
- \`\`\`
72
- ${status}
73
- \`\`\`
74
-
75
- ## Staged Changes
76
- \`\`\`diff
77
- ${stagedDiff || '(no staged changes)'}
78
- \`\`\`
79
-
80
- ## Unstaged Changes
81
- \`\`\`diff
82
- ${unstagedDiff.slice(0, 5000) || '(no unstaged changes)'}
83
- \`\`\`
84
-
85
- ## Recent Commits (for style reference)
86
- \`\`\`
87
- ${recentLog}
88
- \`\`\`
89
-
90
- Instructions:
91
- 1. If there are unstaged changes, suggest which files to stage with \`git add\`
92
- 2. Write a concise commit message (imperative mood, <72 chars title)
93
- 3. Add a body if the changes are complex
94
- 4. Run the git commands to stage and commit
95
-
68
+ return `Generate a git commit for the following changes.
69
+
70
+ ## Git Status
71
+ \`\`\`
72
+ ${status}
73
+ \`\`\`
74
+
75
+ ## Staged Changes
76
+ \`\`\`diff
77
+ ${stagedDiff || '(no staged changes)'}
78
+ \`\`\`
79
+
80
+ ## Unstaged Changes
81
+ \`\`\`diff
82
+ ${unstagedDiff.slice(0, 5000) || '(no unstaged changes)'}
83
+ \`\`\`
84
+
85
+ ## Recent Commits (for style reference)
86
+ \`\`\`
87
+ ${recentLog}
88
+ \`\`\`
89
+
90
+ Instructions:
91
+ 1. If there are unstaged changes, suggest which files to stage with \`git add\`
92
+ 2. Write a concise commit message (imperative mood, <72 chars title)
93
+ 3. Add a body if the changes are complex
94
+ 4. Run the git commands to stage and commit
95
+
96
96
  Follow the existing commit message style from the recent log.`;
97
97
  }
98
98
  /**
@@ -106,27 +106,27 @@ export function buildPRPrompt(cwd) {
106
106
  const diffStat = git(`diff ${baseBranch}...HEAD --stat`, cwd);
107
107
  const log = git(`log ${baseBranch}..HEAD --oneline`, cwd);
108
108
  const diff = git(`diff ${baseBranch}...HEAD`, cwd);
109
- return `Create a GitHub Pull Request for branch \`${branch}\` into \`${baseBranch}\`.
110
-
111
- ## Commits
112
- \`\`\`
113
- ${log}
114
- \`\`\`
115
-
116
- ## Diff Summary
117
- \`\`\`
118
- ${diffStat}
119
- \`\`\`
120
-
121
- ## Full Diff (truncated)
122
- \`\`\`diff
123
- ${diff.slice(0, 10000)}
124
- \`\`\`
125
-
126
- Instructions:
127
- 1. Write a PR title (<70 chars)
128
- 2. Write a description with: Summary (bullet points), Test Plan
129
- 3. Run: gh pr create --title "..." --body "..."
109
+ return `Create a GitHub Pull Request for branch \`${branch}\` into \`${baseBranch}\`.
110
+
111
+ ## Commits
112
+ \`\`\`
113
+ ${log}
114
+ \`\`\`
115
+
116
+ ## Diff Summary
117
+ \`\`\`
118
+ ${diffStat}
119
+ \`\`\`
120
+
121
+ ## Full Diff (truncated)
122
+ \`\`\`diff
123
+ ${diff.slice(0, 10000)}
124
+ \`\`\`
125
+
126
+ Instructions:
127
+ 1. Write a PR title (<70 chars)
128
+ 2. Write a description with: Summary (bullet points), Test Plan
129
+ 3. Run: gh pr create --title "..." --body "..."
130
130
  4. Return the PR URL`;
131
131
  }
132
132
  function detectBaseBranch(cwd) {
package/dist/index.js CHANGED
@@ -79,7 +79,7 @@ import { status as sandboxStatus } from './sandbox.js';
79
79
  // API key rotation pool (/keys)
80
80
  import { listStatus as keyPoolStatus, setPool as syncKeyPool } from './key-rotation.js';
81
81
  // Agentic swarm — fan-out concurrent agents on the same task (/swarm)
82
- import { runSwarm, resolveAgents, formatSwarmResults } from './swarm.js';
82
+ import { buildSwarmAgentTask, buildSwarmPlan, decodeSwarmSentinel, encodeSwarmSentinel, formatSwarmResults, parseSwarmCommandArgs, resolveAgents, runSwarm, } from './swarm.js';
83
83
  // Voice / accessibility — built-in dictation (Whisper) + readout (ElevenLabs)
84
84
  import { printVoiceStatus, isVoiceEnabled, getTtsConfig, getSttConfig, getAccessibilityConfig, speak, dictateOnce, } from './voice.js';
85
85
  import { isFfmpegAvailable, audioCue, startRecording, probeMic, micProbeMessage } from './audio.js';
@@ -123,6 +123,31 @@ function applyModelSelection(config, model, catalogModel) {
123
123
  delete config.contextWindowTokens;
124
124
  }
125
125
  }
126
+ function clipSetupValue(value, max = 120) {
127
+ const single = value.replace(/\s+/g, ' ').trim();
128
+ return single.length <= max ? single : single.slice(0, max - 1) + '…';
129
+ }
130
+ async function runSwarmSetupWizard(rl, plan) {
131
+ if (!stdin.isTTY || process.env.CAWDEX_SWARM_WIZARD === '0')
132
+ return plan;
133
+ const next = {
134
+ ...plan,
135
+ setup: { ...plan.setup },
136
+ };
137
+ const ask = async (label, current) => {
138
+ const prompt = theme.dim(` ${label}`) + theme.syntaxPunctuation(` [${clipSetupValue(current)}]: `);
139
+ const answer = (await rl.question(prompt)).trim();
140
+ return answer || current;
141
+ };
142
+ console.log(theme.header(' Swarm setup'));
143
+ console.log(theme.dim(' Press Enter to accept an inferred value, or type a correction.'));
144
+ next.setup.goal = await ask('Goal', next.setup.goal);
145
+ next.setup.budget = await ask('Budget/time', next.setup.budget);
146
+ next.setup.target = await ask('Target platform/stack', next.setup.target);
147
+ next.setup.assets = await ask('Starting assets/resources', next.setup.assets);
148
+ next.setup.quality = await ask('Quality bar/release target', next.setup.quality);
149
+ return next;
150
+ }
126
151
  // ── Setup Wizard ──────────────────────────────────────────
127
152
  function printCommandHelp(query) {
128
153
  const resolved = resolveCommandEntry(query);
@@ -780,7 +805,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
780
805
  // silent aliases for power users but are not listed here.
781
806
  console.log(h('\n ── Orchestration ──'));
782
807
  console.log(d(' ') + c('/orchestrate <task>') + d(' — decompose into parallel sub-agents'));
783
- console.log(d(' ') + c('/swarm <agents> <task>') + d(' — true parallel fan-out: N agents on same task, results merged with attribution'));
808
+ console.log(d(' ') + c('/swarm <task>') + d(' — infer roles, run analysis-only agents, synthesize a handoff (expert: /swarm <agents> <task>)'));
784
809
  console.log(d(' ') + c('/pr-loop') + d(' — autonomous PR review loop'));
785
810
  console.log(d(' ') + c('/multi-plan <task>') + d(' — multi-agent planning'));
786
811
  console.log(d(' ') + c('/multi-execute') + d(' — multi-agent execution'));
@@ -1365,9 +1390,7 @@ export function handleSlashCommand(input, config, messages, session, mode) {
1365
1390
  return { handled: true };
1366
1391
  case '/resume': {
1367
1392
  if (!args.trim()) {
1368
- console.log(chalk.yellow(' Usage: /resume <session-id> | <prefix> | last'));
1369
- console.log(chalk.dim(' /sessions lists what\'s saved.'));
1370
- return { handled: true };
1393
+ return { handled: true, injectPrompt: '__RESUME_PICK__' };
1371
1394
  }
1372
1395
  // resolveSessionRef accepts exact ID, prefix match (like git),
1373
1396
  // "last"/"latest" shortcut, and strips angle/quote wrappers
@@ -1728,29 +1751,19 @@ export function handleSlashCommand(input, config, messages, session, mode) {
1728
1751
  mode.current = 'architect';
1729
1752
  const orchPrompt = buildOrchestrationPrompt(args);
1730
1753
  return { handled: false, injectPrompt: orchPrompt };
1731
- // ── Agentic swarm — true parallel fan-out (M3 swarm audit) ──
1732
- // Run N agents concurrently on the same task. Each agent gets its
1733
- // own ECC prompt + the task as user message; outputs are merged
1734
- // with attribution headers. No tools available to swarm agents
1735
- // analysis only, no file edits.
1736
- //
1737
- // /swarm <agent1,agent2,...> <task>
1738
- //
1739
- // Each agent's request uses the key rotation pool from v1.23.0,
1740
- // so multi-account users get true parallel throughput.
1754
+ // ── Agentic swarm ─────────────────────────────────
1755
+ // Default: /swarm <natural task>. Cawdex infers roles, runs them
1756
+ // analysis-only, then hands the synthesis back to the main agent.
1757
+ // Expert shortcut remains: /swarm <agent1,agent2> <task>.
1741
1758
  case '/swarm': {
1742
- // Match: first whitespace-free token is the agents list, rest is task
1743
- const m = args.match(/^(\S+)\s+([\s\S]+)$/);
1744
- if (!m) {
1745
- console.log(chalk.yellow(' Usage: /swarm <agent1,agent2,...> <task>'));
1746
- console.log(chalk.dim(' Example: /swarm code-architect,silent-failure-hunter,type-design-analyzer audit the auth flow'));
1747
- console.log(chalk.dim(' Run /ecc-guide agents to see available agents.'));
1759
+ const parsed = parseSwarmCommandArgs(args);
1760
+ if ('error' in parsed) {
1761
+ console.log(chalk.yellow(` ${parsed.error}`));
1762
+ console.log(chalk.dim(' Example: /swarm Build a working browser game with tests'));
1763
+ console.log(chalk.dim(' Expert: /swarm code-architect,silent-failure-hunter audit the auth flow'));
1748
1764
  return { handled: true };
1749
1765
  }
1750
- const [, agentsList, task] = m;
1751
- // Use a sentinel + delimiter approach so the main REPL loop can
1752
- // pick up the async swarm dispatch (slash handlers are sync).
1753
- return { handled: false, injectPrompt: '__SWARM__' + agentsList + '|||' + task };
1766
+ return { handled: true, injectPrompt: encodeSwarmSentinel(parsed.payload) };
1754
1767
  }
1755
1768
  // ── Verification & Build ─────────────────────────
1756
1769
  case '/verify': {
@@ -3336,12 +3349,7 @@ async function main() {
3336
3349
  // saved before that check landed never see the warning. Print it
3337
3350
  // every launch so they get a chance to switch via /model before
3338
3351
  // they hit the "model returns nothing, REPL looks frozen" footgun.
3339
- const flakyPatterns = [
3340
- 'owl-alpha', 'horizon-alpha', 'horizon-beta',
3341
- 'optimus-alpha', 'quasar-alpha',
3342
- ];
3343
- const lowerModelAtLaunch = (config.model || '').toLowerCase();
3344
- if (flakyPatterns.some((p) => lowerModelAtLaunch.includes(p))) {
3352
+ if (isKnownFlakyOpenRouterModel(config)) {
3345
3353
  console.log(theme.warning(` ⚠ Active model "${config.model}" is an experimental / free model known to`));
3346
3354
  console.log(theme.warning(` return empty or "ERROR" responses, or get stuck in token loops.`));
3347
3355
  console.log(theme.dim(` Switch with /openrouter-free or /model openrouter/free.`));
@@ -4393,6 +4401,26 @@ async function main() {
4393
4401
  }
4394
4402
  continue;
4395
4403
  }
4404
+ else if (result.injectPrompt === '__RESUME_PICK__') {
4405
+ const sessions = listSessions();
4406
+ if (sessions.length === 0) {
4407
+ console.log(theme.dim(' No saved sessions.'));
4408
+ continue;
4409
+ }
4410
+ const { pickSession } = await import('./session-picker.js');
4411
+ const selectedId = await pickSession(sessions, { title: 'Cawdex · resume session' });
4412
+ if (!selectedId) {
4413
+ console.log(theme.dim(' Cancelled — session unchanged.'));
4414
+ continue;
4415
+ }
4416
+ const resumeResult = handleSlashCommand(`/resume ${selectedId}`, config, messages, session, mode);
4417
+ if (resumeResult.newMessages !== undefined) {
4418
+ messages.length = 0;
4419
+ messages.push(...resumeResult.newMessages);
4420
+ }
4421
+ await saveWithSnapshot();
4422
+ continue;
4423
+ }
4396
4424
  else if (result.injectPrompt === '__OPENAI_OAUTH_SMOKE__') {
4397
4425
  const smoke = await runOpenAICodexSmokeTest(config);
4398
4426
  console.log(formatOpenAICodexSmokeResult(smoke));
@@ -4432,29 +4460,30 @@ async function main() {
4432
4460
  continue;
4433
4461
  }
4434
4462
  else if (result.injectPrompt.startsWith('__SWARM__')) {
4435
- // Swarm dispatch: __SWARM__<agentsCsv>|||<task>. Same sentinel
4436
- // trick as /dictate so the slash handler stays sync; the async
4437
- // fan-out happens here in the main REPL loop where we already
4438
- // have await + the live config object.
4439
- const payload = result.injectPrompt.slice('__SWARM__'.length);
4440
- const sepIdx = payload.indexOf('|||');
4441
- const agentsCsv = payload.slice(0, sepIdx);
4442
- const task = payload.slice(sepIdx + 3);
4443
- const slugs = agentsCsv.split(',').map((s) => s.trim()).filter(Boolean);
4463
+ const payload = decodeSwarmSentinel(result.injectPrompt);
4464
+ if (!payload) {
4465
+ console.log(chalk.yellow(' /swarm: could not parse swarm payload.'));
4466
+ continue;
4467
+ }
4468
+ let plan = buildSwarmPlan(payload);
4469
+ if (payload.mode === 'auto') {
4470
+ plan = await runSwarmSetupWizard(rl, plan);
4471
+ }
4444
4472
  try {
4445
- const agents = resolveAgents(slugs);
4446
- console.log(chalk.cyan(` Swarming ${agents.length} agent(s) in parallel: ${agents.map((a) => a.name).join(', ')}`));
4447
- console.log(chalk.dim(` Task: ${task.length > 100 ? task.slice(0, 97) + '...' : task}`));
4473
+ const agents = resolveAgents(plan.agents);
4474
+ console.log(chalk.cyan(` Swarming ${agents.length} agent(s): ${agents.map((a) => a.name).join(', ')}`));
4475
+ console.log(chalk.dim(` Task: ${plan.task.length > 100 ? plan.task.slice(0, 97) + '...' : plan.task}`));
4476
+ console.log(chalk.dim(' Setup: goal, budget/time, platform, assets, quality bar inferred; workers stay analysis-only.'));
4448
4477
  const swarmStart = Date.now();
4449
- const results = await runSwarm(agents, task, config);
4450
- const output = formatSwarmResults(results);
4478
+ const results = await runSwarm(agents, buildSwarmAgentTask(plan), config);
4479
+ const output = formatSwarmResults(results, plan);
4451
4480
  console.log(output);
4452
4481
  const elapsed = ((Date.now() - swarmStart) / 1000).toFixed(1);
4453
4482
  const ok = results.filter((r) => !r.error).length;
4454
4483
  console.log(chalk.dim(`\n swarm complete: ${ok}/${results.length} agent(s) succeeded in ${elapsed}s`));
4455
4484
  // Push the swarm as conversational context so follow-up
4456
4485
  // turns can reason about the consolidated output.
4457
- messages.push({ role: 'user', content: `[/swarm ${agents.map((a) => a.name).join(',')}] ${task}` });
4486
+ messages.push({ role: 'user', content: `[/swarm ${payload.mode === 'legacy' ? agents.map((a) => a.name).join(',') + ' ' : ''}${plan.task}]` });
4458
4487
  messages.push({ role: 'assistant', content: output.slice(0, 8000) });
4459
4488
  }
4460
4489
  catch (e) {