@kynetic-ai/spec 0.1.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 +263 -0
- package/dist/acp/client.d.ts +159 -0
- package/dist/acp/client.d.ts.map +1 -0
- package/dist/acp/client.js +255 -0
- package/dist/acp/client.js.map +1 -0
- package/dist/acp/framing.d.ts +119 -0
- package/dist/acp/framing.d.ts.map +1 -0
- package/dist/acp/framing.js +302 -0
- package/dist/acp/framing.js.map +1 -0
- package/dist/acp/index.d.ts +14 -0
- package/dist/acp/index.d.ts.map +1 -0
- package/dist/acp/index.js +13 -0
- package/dist/acp/index.js.map +1 -0
- package/dist/acp/types.d.ts +89 -0
- package/dist/acp/types.d.ts.map +1 -0
- package/dist/acp/types.js +99 -0
- package/dist/acp/types.js.map +1 -0
- package/dist/agents/adapters.d.ts +55 -0
- package/dist/agents/adapters.d.ts.map +1 -0
- package/dist/agents/adapters.js +84 -0
- package/dist/agents/adapters.js.map +1 -0
- package/dist/agents/index.d.ts +8 -0
- package/dist/agents/index.d.ts.map +1 -0
- package/dist/agents/index.js +10 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/agents/spawner.d.ts +53 -0
- package/dist/agents/spawner.d.ts.map +1 -0
- package/dist/agents/spawner.js +83 -0
- package/dist/agents/spawner.js.map +1 -0
- package/dist/cli/batch.d.ts +82 -0
- package/dist/cli/batch.d.ts.map +1 -0
- package/dist/cli/batch.js +162 -0
- package/dist/cli/batch.js.map +1 -0
- package/dist/cli/commands/clone-for-testing.d.ts +6 -0
- package/dist/cli/commands/clone-for-testing.d.ts.map +1 -0
- package/dist/cli/commands/clone-for-testing.js +176 -0
- package/dist/cli/commands/clone-for-testing.js.map +1 -0
- package/dist/cli/commands/derive.d.ts +6 -0
- package/dist/cli/commands/derive.d.ts.map +1 -0
- package/dist/cli/commands/derive.js +450 -0
- package/dist/cli/commands/derive.js.map +1 -0
- package/dist/cli/commands/help.d.ts +6 -0
- package/dist/cli/commands/help.d.ts.map +1 -0
- package/dist/cli/commands/help.js +196 -0
- package/dist/cli/commands/help.js.map +1 -0
- package/dist/cli/commands/inbox.d.ts +6 -0
- package/dist/cli/commands/inbox.d.ts.map +1 -0
- package/dist/cli/commands/inbox.js +235 -0
- package/dist/cli/commands/inbox.js.map +1 -0
- package/dist/cli/commands/index.d.ts +20 -0
- package/dist/cli/commands/index.d.ts.map +1 -0
- package/dist/cli/commands/index.js +21 -0
- package/dist/cli/commands/index.js.map +1 -0
- package/dist/cli/commands/init.d.ts +6 -0
- package/dist/cli/commands/init.d.ts.map +1 -0
- package/dist/cli/commands/init.js +245 -0
- package/dist/cli/commands/init.js.map +1 -0
- package/dist/cli/commands/item.d.ts +6 -0
- package/dist/cli/commands/item.d.ts.map +1 -0
- package/dist/cli/commands/item.js +1311 -0
- package/dist/cli/commands/item.js.map +1 -0
- package/dist/cli/commands/link.d.ts +6 -0
- package/dist/cli/commands/link.d.ts.map +1 -0
- package/dist/cli/commands/link.js +288 -0
- package/dist/cli/commands/link.js.map +1 -0
- package/dist/cli/commands/log.d.ts +16 -0
- package/dist/cli/commands/log.d.ts.map +1 -0
- package/dist/cli/commands/log.js +291 -0
- package/dist/cli/commands/log.js.map +1 -0
- package/dist/cli/commands/meta.d.ts +15 -0
- package/dist/cli/commands/meta.d.ts.map +1 -0
- package/dist/cli/commands/meta.js +1378 -0
- package/dist/cli/commands/meta.js.map +1 -0
- package/dist/cli/commands/module.d.ts +6 -0
- package/dist/cli/commands/module.d.ts.map +1 -0
- package/dist/cli/commands/module.js +102 -0
- package/dist/cli/commands/module.js.map +1 -0
- package/dist/cli/commands/ralph.d.ts +9 -0
- package/dist/cli/commands/ralph.d.ts.map +1 -0
- package/dist/cli/commands/ralph.js +465 -0
- package/dist/cli/commands/ralph.js.map +1 -0
- package/dist/cli/commands/search.d.ts +6 -0
- package/dist/cli/commands/search.d.ts.map +1 -0
- package/dist/cli/commands/search.js +134 -0
- package/dist/cli/commands/search.js.map +1 -0
- package/dist/cli/commands/session.d.ts +164 -0
- package/dist/cli/commands/session.d.ts.map +1 -0
- package/dist/cli/commands/session.js +745 -0
- package/dist/cli/commands/session.js.map +1 -0
- package/dist/cli/commands/setup.d.ts +26 -0
- package/dist/cli/commands/setup.d.ts.map +1 -0
- package/dist/cli/commands/setup.js +586 -0
- package/dist/cli/commands/setup.js.map +1 -0
- package/dist/cli/commands/shadow.d.ts +6 -0
- package/dist/cli/commands/shadow.d.ts.map +1 -0
- package/dist/cli/commands/shadow.js +299 -0
- package/dist/cli/commands/shadow.js.map +1 -0
- package/dist/cli/commands/task.d.ts +6 -0
- package/dist/cli/commands/task.d.ts.map +1 -0
- package/dist/cli/commands/task.js +1514 -0
- package/dist/cli/commands/task.js.map +1 -0
- package/dist/cli/commands/tasks.d.ts +6 -0
- package/dist/cli/commands/tasks.d.ts.map +1 -0
- package/dist/cli/commands/tasks.js +347 -0
- package/dist/cli/commands/tasks.js.map +1 -0
- package/dist/cli/commands/trait.d.ts +10 -0
- package/dist/cli/commands/trait.d.ts.map +1 -0
- package/dist/cli/commands/trait.js +295 -0
- package/dist/cli/commands/trait.js.map +1 -0
- package/dist/cli/commands/validate.d.ts +6 -0
- package/dist/cli/commands/validate.d.ts.map +1 -0
- package/dist/cli/commands/validate.js +626 -0
- package/dist/cli/commands/validate.js.map +1 -0
- package/dist/cli/exit-codes.d.ts +62 -0
- package/dist/cli/exit-codes.d.ts.map +1 -0
- package/dist/cli/exit-codes.js +65 -0
- package/dist/cli/exit-codes.js.map +1 -0
- package/dist/cli/help/content.d.ts +35 -0
- package/dist/cli/help/content.d.ts.map +1 -0
- package/dist/cli/help/content.js +312 -0
- package/dist/cli/help/content.js.map +1 -0
- package/dist/cli/index.d.ts +5 -0
- package/dist/cli/index.d.ts.map +1 -0
- package/dist/cli/index.js +85 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/cli/introspection.d.ts +87 -0
- package/dist/cli/introspection.d.ts.map +1 -0
- package/dist/cli/introspection.js +127 -0
- package/dist/cli/introspection.js.map +1 -0
- package/dist/cli/output.d.ts +56 -0
- package/dist/cli/output.d.ts.map +1 -0
- package/dist/cli/output.js +467 -0
- package/dist/cli/output.js.map +1 -0
- package/dist/cli/suggest.d.ts +16 -0
- package/dist/cli/suggest.d.ts.map +1 -0
- package/dist/cli/suggest.js +72 -0
- package/dist/cli/suggest.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/index.js.map +1 -0
- package/dist/parser/alignment.d.ts +113 -0
- package/dist/parser/alignment.d.ts.map +1 -0
- package/dist/parser/alignment.js +261 -0
- package/dist/parser/alignment.js.map +1 -0
- package/dist/parser/assess.d.ts +81 -0
- package/dist/parser/assess.d.ts.map +1 -0
- package/dist/parser/assess.js +197 -0
- package/dist/parser/assess.js.map +1 -0
- package/dist/parser/convention-validation.d.ts +48 -0
- package/dist/parser/convention-validation.d.ts.map +1 -0
- package/dist/parser/convention-validation.js +167 -0
- package/dist/parser/convention-validation.js.map +1 -0
- package/dist/parser/fix.d.ts +38 -0
- package/dist/parser/fix.d.ts.map +1 -0
- package/dist/parser/fix.js +185 -0
- package/dist/parser/fix.js.map +1 -0
- package/dist/parser/index.d.ts +12 -0
- package/dist/parser/index.d.ts.map +1 -0
- package/dist/parser/index.js +13 -0
- package/dist/parser/index.js.map +1 -0
- package/dist/parser/items.d.ts +138 -0
- package/dist/parser/items.d.ts.map +1 -0
- package/dist/parser/items.js +321 -0
- package/dist/parser/items.js.map +1 -0
- package/dist/parser/meta.d.ts +120 -0
- package/dist/parser/meta.d.ts.map +1 -0
- package/dist/parser/meta.js +441 -0
- package/dist/parser/meta.js.map +1 -0
- package/dist/parser/refs.d.ts +185 -0
- package/dist/parser/refs.d.ts.map +1 -0
- package/dist/parser/refs.js +404 -0
- package/dist/parser/refs.js.map +1 -0
- package/dist/parser/shadow.d.ts +253 -0
- package/dist/parser/shadow.d.ts.map +1 -0
- package/dist/parser/shadow.js +1053 -0
- package/dist/parser/shadow.js.map +1 -0
- package/dist/parser/traits.d.ts +72 -0
- package/dist/parser/traits.d.ts.map +1 -0
- package/dist/parser/traits.js +120 -0
- package/dist/parser/traits.js.map +1 -0
- package/dist/parser/validate.d.ts +89 -0
- package/dist/parser/validate.d.ts.map +1 -0
- package/dist/parser/validate.js +817 -0
- package/dist/parser/validate.js.map +1 -0
- package/dist/parser/yaml.d.ts +326 -0
- package/dist/parser/yaml.d.ts.map +1 -0
- package/dist/parser/yaml.js +1383 -0
- package/dist/parser/yaml.js.map +1 -0
- package/dist/ralph/cli-renderer.d.ts +20 -0
- package/dist/ralph/cli-renderer.d.ts.map +1 -0
- package/dist/ralph/cli-renderer.js +179 -0
- package/dist/ralph/cli-renderer.js.map +1 -0
- package/dist/ralph/events.d.ts +65 -0
- package/dist/ralph/events.d.ts.map +1 -0
- package/dist/ralph/events.js +397 -0
- package/dist/ralph/events.js.map +1 -0
- package/dist/ralph/index.d.ts +8 -0
- package/dist/ralph/index.d.ts.map +1 -0
- package/dist/ralph/index.js +10 -0
- package/dist/ralph/index.js.map +1 -0
- package/dist/schema/common.d.ts +46 -0
- package/dist/schema/common.d.ts.map +1 -0
- package/dist/schema/common.js +71 -0
- package/dist/schema/common.js.map +1 -0
- package/dist/schema/inbox.d.ts +90 -0
- package/dist/schema/inbox.d.ts.map +1 -0
- package/dist/schema/inbox.js +30 -0
- package/dist/schema/inbox.js.map +1 -0
- package/dist/schema/index.d.ts +6 -0
- package/dist/schema/index.d.ts.map +1 -0
- package/dist/schema/index.js +7 -0
- package/dist/schema/index.js.map +1 -0
- package/dist/schema/meta.d.ts +762 -0
- package/dist/schema/meta.d.ts.map +1 -0
- package/dist/schema/meta.js +144 -0
- package/dist/schema/meta.js.map +1 -0
- package/dist/schema/spec.d.ts +912 -0
- package/dist/schema/spec.d.ts.map +1 -0
- package/dist/schema/spec.js +104 -0
- package/dist/schema/spec.js.map +1 -0
- package/dist/schema/task.d.ts +664 -0
- package/dist/schema/task.d.ts.map +1 -0
- package/dist/schema/task.js +130 -0
- package/dist/schema/task.js.map +1 -0
- package/dist/sessions/index.d.ts +11 -0
- package/dist/sessions/index.d.ts.map +1 -0
- package/dist/sessions/index.js +13 -0
- package/dist/sessions/index.js.map +1 -0
- package/dist/sessions/store.d.ts +144 -0
- package/dist/sessions/store.d.ts.map +1 -0
- package/dist/sessions/store.js +325 -0
- package/dist/sessions/store.js.map +1 -0
- package/dist/sessions/types.d.ts +157 -0
- package/dist/sessions/types.d.ts.map +1 -0
- package/dist/sessions/types.js +90 -0
- package/dist/sessions/types.js.map +1 -0
- package/dist/strings/errors.d.ts +420 -0
- package/dist/strings/errors.d.ts.map +1 -0
- package/dist/strings/errors.js +282 -0
- package/dist/strings/errors.js.map +1 -0
- package/dist/strings/guidance.d.ts +65 -0
- package/dist/strings/guidance.d.ts.map +1 -0
- package/dist/strings/guidance.js +66 -0
- package/dist/strings/guidance.js.map +1 -0
- package/dist/strings/index.d.ts +12 -0
- package/dist/strings/index.d.ts.map +1 -0
- package/dist/strings/index.js +12 -0
- package/dist/strings/index.js.map +1 -0
- package/dist/strings/labels.d.ts +74 -0
- package/dist/strings/labels.d.ts.map +1 -0
- package/dist/strings/labels.js +75 -0
- package/dist/strings/labels.js.map +1 -0
- package/dist/strings/validation.d.ts +126 -0
- package/dist/strings/validation.d.ts.map +1 -0
- package/dist/strings/validation.js +135 -0
- package/dist/strings/validation.js.map +1 -0
- package/dist/utils/commit.d.ts +23 -0
- package/dist/utils/commit.d.ts.map +1 -0
- package/dist/utils/commit.js +67 -0
- package/dist/utils/commit.js.map +1 -0
- package/dist/utils/git.d.ts +57 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +192 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/grep.d.ts +28 -0
- package/dist/utils/grep.d.ts.map +1 -0
- package/dist/utils/grep.js +86 -0
- package/dist/utils/grep.js.map +1 -0
- package/dist/utils/index.d.ts +8 -0
- package/dist/utils/index.d.ts.map +1 -0
- package/dist/utils/index.js +6 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/time.d.ts +18 -0
- package/dist/utils/time.d.ts.map +1 -0
- package/dist/utils/time.js +61 -0
- package/dist/utils/time.js.map +1 -0
- package/package.json +62 -0
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ralph command - automated task loop via ACP.
|
|
3
|
+
*
|
|
4
|
+
* Runs an ACP-compliant agent in a loop to process tasks autonomously.
|
|
5
|
+
* Uses session event storage for full audit trail and streaming output.
|
|
6
|
+
*/
|
|
7
|
+
import chalk from 'chalk';
|
|
8
|
+
import { ulid } from 'ulid';
|
|
9
|
+
import * as fs from 'node:fs/promises';
|
|
10
|
+
import * as path from 'node:path';
|
|
11
|
+
import { spawn, spawnSync } from 'node:child_process';
|
|
12
|
+
import { initContext } from '../../parser/index.js';
|
|
13
|
+
import { error, info, success } from '../output.js';
|
|
14
|
+
import { gatherSessionContext } from './session.js';
|
|
15
|
+
import { resolveAdapter, registerAdapter } from '../../agents/index.js';
|
|
16
|
+
import { spawnAndInitialize } from '../../agents/spawner.js';
|
|
17
|
+
import { createSession, updateSessionStatus, appendEvent, saveSessionContext, } from '../../sessions/index.js';
|
|
18
|
+
import { createTranslator, createCliRenderer } from '../../ralph/index.js';
|
|
19
|
+
import { errors } from '../../strings/index.js';
|
|
20
|
+
import { EXIT_CODES } from '../exit-codes.js';
|
|
21
|
+
// ─── Prompt Template ─────────────────────────────────────────────────────────
|
|
22
|
+
function buildPrompt(sessionCtx, iteration, maxLoops, focus) {
|
|
23
|
+
const isFinal = iteration === maxLoops;
|
|
24
|
+
const focusSection = focus ? `
|
|
25
|
+
## Session Focus (applies to ALL iterations)
|
|
26
|
+
|
|
27
|
+
> **${focus}**
|
|
28
|
+
|
|
29
|
+
Keep this focus in mind throughout your work. It takes priority over default task selection.
|
|
30
|
+
` : '';
|
|
31
|
+
return `# Kspec Automation Session
|
|
32
|
+
|
|
33
|
+
You are running as part of a kspec automation loop. This is iteration ${iteration} of ${maxLoops}.
|
|
34
|
+
${focusSection}
|
|
35
|
+
|
|
36
|
+
## Current State
|
|
37
|
+
\`\`\`json
|
|
38
|
+
${JSON.stringify(sessionCtx, null, 2)}
|
|
39
|
+
\`\`\`
|
|
40
|
+
|
|
41
|
+
## Working Procedure
|
|
42
|
+
|
|
43
|
+
1. **Pick a task**: Review ready_tasks above. Pick the highest priority task (lowest number = higher priority). If there's an active (in_progress) task, continue that instead.
|
|
44
|
+
|
|
45
|
+
2. **Start the task** (if not already in_progress):
|
|
46
|
+
\`\`\`bash
|
|
47
|
+
kspec task start @task-ref
|
|
48
|
+
\`\`\`
|
|
49
|
+
|
|
50
|
+
3. **Do the work**:
|
|
51
|
+
- Read relevant files to understand the task
|
|
52
|
+
- Make changes as needed
|
|
53
|
+
- Run tests if applicable
|
|
54
|
+
- Document as you go with task notes
|
|
55
|
+
|
|
56
|
+
4. **Document progress**:
|
|
57
|
+
\`\`\`bash
|
|
58
|
+
kspec task note @task-ref "What you did, decisions made, etc."
|
|
59
|
+
\`\`\`
|
|
60
|
+
|
|
61
|
+
5. **Submit or checkpoint**:
|
|
62
|
+
- If code is DONE (ready for PR):
|
|
63
|
+
\`\`\`bash
|
|
64
|
+
kspec task submit @task-ref
|
|
65
|
+
\`\`\`
|
|
66
|
+
- If task is NOT done (WIP):
|
|
67
|
+
\`\`\`bash
|
|
68
|
+
kspec task note @task-ref "WIP: What's done, what remains..."
|
|
69
|
+
\`\`\`
|
|
70
|
+
|
|
71
|
+
6. **Commit your work**:
|
|
72
|
+
\`\`\`bash
|
|
73
|
+
git add -A && git commit -m "feat/fix/chore: description
|
|
74
|
+
|
|
75
|
+
Task: @task-ref"
|
|
76
|
+
\`\`\`
|
|
77
|
+
|
|
78
|
+
7. **Reflect on this iteration**:
|
|
79
|
+
Think about what you learned, any friction points, or patterns worth remembering.
|
|
80
|
+
|
|
81
|
+
For **systemic patterns** (friction or success worth documenting):
|
|
82
|
+
\`\`\`bash
|
|
83
|
+
kspec meta observe friction "Description of systemic issue..."
|
|
84
|
+
kspec meta observe success "Pattern worth replicating..."
|
|
85
|
+
\`\`\`
|
|
86
|
+
|
|
87
|
+
For **actionable improvements** (specific ideas that could become tasks):
|
|
88
|
+
\`\`\`bash
|
|
89
|
+
kspec inbox add "Improvement idea..." --tag reflection
|
|
90
|
+
\`\`\`
|
|
91
|
+
|
|
92
|
+
## Important Notes
|
|
93
|
+
- Stay focused on ONE task per iteration
|
|
94
|
+
- The loop continues automatically - don't worry about picking the next task
|
|
95
|
+
- kspec tracks state across iterations via task status and notes
|
|
96
|
+
- Always commit before the iteration ends
|
|
97
|
+
- Always reflect and capture at least one observation
|
|
98
|
+
${isFinal ? `
|
|
99
|
+
## FINAL ITERATION
|
|
100
|
+
This is the last iteration of the loop. After completing your work:
|
|
101
|
+
1. Commit any remaining changes
|
|
102
|
+
2. Reflect on the overall session
|
|
103
|
+
3. Capture any final insights as observations
|
|
104
|
+
` : ''}`;
|
|
105
|
+
}
|
|
106
|
+
// ─── Streaming Output ────────────────────────────────────────────────────────
|
|
107
|
+
// Translator and renderer are created per-session in the action handler.
|
|
108
|
+
// This allows the architecture to be reused by future TUI renderers.
|
|
109
|
+
// ─── Adapter Validation ──────────────────────────────────────────────────────
|
|
110
|
+
// AC: @ralph-adapter-validation valid-adapter-proceeds, invalid-adapter-error, validation-before-spawn
|
|
111
|
+
/**
|
|
112
|
+
* Validate that the specified ACP adapter package exists.
|
|
113
|
+
* Uses npx --no-install to check both global and local node_modules.
|
|
114
|
+
*
|
|
115
|
+
* @throws {Error} Never throws - exits process with code 3 if validation fails
|
|
116
|
+
*/
|
|
117
|
+
function validateAdapter(adapterPackage) {
|
|
118
|
+
// Use npx --no-install with --version to check if package exists
|
|
119
|
+
// This checks both global and local node_modules, handles scoped packages
|
|
120
|
+
const result = spawnSync('npx', ['--no-install', adapterPackage, '--version'], {
|
|
121
|
+
encoding: 'utf-8',
|
|
122
|
+
stdio: 'pipe',
|
|
123
|
+
});
|
|
124
|
+
if (result.status !== 0) {
|
|
125
|
+
error(`Adapter package not found: ${adapterPackage}. Install with: npm install -g ${adapterPackage}`);
|
|
126
|
+
process.exit(EXIT_CODES.NOT_FOUND);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
// ─── Tool Request Handler ────────────────────────────────────────────────────
|
|
130
|
+
/**
|
|
131
|
+
* Handle tool requests from ACP agent.
|
|
132
|
+
* Implements file operations, terminal commands, and permission handling.
|
|
133
|
+
*/
|
|
134
|
+
async function handleRequest(client, id, method, params, yolo) {
|
|
135
|
+
const p = params;
|
|
136
|
+
try {
|
|
137
|
+
switch (method) {
|
|
138
|
+
case 'session/request_permission': {
|
|
139
|
+
// In yolo mode, auto-approve all permissions
|
|
140
|
+
// In normal mode, would need to implement permission UI
|
|
141
|
+
const options = p.options || [];
|
|
142
|
+
if (yolo) {
|
|
143
|
+
// Find an "allow" option (prefer allow_always, then allow_once)
|
|
144
|
+
const allowOption = options.find(o => o.kind === 'allow_always')
|
|
145
|
+
|| options.find(o => o.kind === 'allow_once');
|
|
146
|
+
if (allowOption) {
|
|
147
|
+
client.respondPermission(id, {
|
|
148
|
+
outcome: { outcome: 'selected', optionId: allowOption.optionId },
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
else {
|
|
152
|
+
// No allow option available - cancel
|
|
153
|
+
client.respondPermission(id, { outcome: { outcome: 'cancelled' } });
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
else {
|
|
157
|
+
// TODO: Implement permission prompting
|
|
158
|
+
client.respondPermission(id, { outcome: { outcome: 'cancelled' } });
|
|
159
|
+
}
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
case 'file/read': {
|
|
163
|
+
const filePath = p.path;
|
|
164
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
165
|
+
client.respond(id, { content });
|
|
166
|
+
break;
|
|
167
|
+
}
|
|
168
|
+
case 'file/write': {
|
|
169
|
+
const filePath = p.path;
|
|
170
|
+
const content = p.content;
|
|
171
|
+
await fs.mkdir(path.dirname(filePath), { recursive: true });
|
|
172
|
+
await fs.writeFile(filePath, content, 'utf-8');
|
|
173
|
+
client.respond(id, {});
|
|
174
|
+
break;
|
|
175
|
+
}
|
|
176
|
+
case 'terminal/run': {
|
|
177
|
+
const command = p.command;
|
|
178
|
+
const cwd = p.cwd || process.cwd();
|
|
179
|
+
const timeout = p.timeout || 60000;
|
|
180
|
+
const result = await new Promise((resolve) => {
|
|
181
|
+
const child = spawn(command, [], {
|
|
182
|
+
cwd,
|
|
183
|
+
shell: true,
|
|
184
|
+
timeout,
|
|
185
|
+
});
|
|
186
|
+
let stdout = '';
|
|
187
|
+
let stderr = '';
|
|
188
|
+
child.stdout?.on('data', (data) => {
|
|
189
|
+
stdout += data.toString();
|
|
190
|
+
});
|
|
191
|
+
child.stderr?.on('data', (data) => {
|
|
192
|
+
stderr += data.toString();
|
|
193
|
+
});
|
|
194
|
+
child.on('close', (code) => {
|
|
195
|
+
resolve({ stdout, stderr, exitCode: code ?? 1 });
|
|
196
|
+
});
|
|
197
|
+
child.on('error', (err) => {
|
|
198
|
+
resolve({ stdout, stderr: err.message, exitCode: 1 });
|
|
199
|
+
});
|
|
200
|
+
});
|
|
201
|
+
client.respond(id, result);
|
|
202
|
+
break;
|
|
203
|
+
}
|
|
204
|
+
default:
|
|
205
|
+
// Unknown method - return error
|
|
206
|
+
client.respondError(id, -32601, `Method not found: ${method}`);
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
catch (err) {
|
|
210
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
211
|
+
client.respondError(id, -32000, message);
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
// ─── Command Registration ────────────────────────────────────────────────────
|
|
215
|
+
export function registerRalphCommand(program) {
|
|
216
|
+
program
|
|
217
|
+
.command('ralph')
|
|
218
|
+
.description('Run ACP agent in a loop to process ready tasks')
|
|
219
|
+
.option('--max-loops <n>', 'Maximum iterations', '5')
|
|
220
|
+
.option('--max-retries <n>', 'Max retries per iteration on error', '3')
|
|
221
|
+
.option('--max-failures <n>', 'Max consecutive failed iterations before exit', '3')
|
|
222
|
+
.option('--dry-run', 'Show prompt without executing')
|
|
223
|
+
.option('--yolo', 'Use dangerously-skip-permissions (default)', true)
|
|
224
|
+
.option('--no-yolo', 'Require normal permission prompts')
|
|
225
|
+
.option('--adapter <id>', 'Agent adapter to use', 'claude-code-acp')
|
|
226
|
+
.option('--adapter-cmd <cmd>', 'Custom adapter command (for testing)')
|
|
227
|
+
.option('--focus <instructions>', 'Focus instructions included in every iteration prompt')
|
|
228
|
+
.action(async (options) => {
|
|
229
|
+
try {
|
|
230
|
+
const maxLoops = parseInt(options.maxLoops, 10);
|
|
231
|
+
const maxRetries = parseInt(options.maxRetries, 10);
|
|
232
|
+
const maxFailures = parseInt(options.maxFailures, 10);
|
|
233
|
+
if (isNaN(maxLoops) || maxLoops < 1) {
|
|
234
|
+
error(errors.usage.maxLoopsPositive);
|
|
235
|
+
process.exit(EXIT_CODES.ERROR);
|
|
236
|
+
}
|
|
237
|
+
if (isNaN(maxRetries) || maxRetries < 0) {
|
|
238
|
+
error(errors.usage.maxRetriesNonNegative);
|
|
239
|
+
process.exit(EXIT_CODES.ERROR);
|
|
240
|
+
}
|
|
241
|
+
if (isNaN(maxFailures) || maxFailures < 1) {
|
|
242
|
+
error(errors.usage.maxFailuresPositive);
|
|
243
|
+
process.exit(EXIT_CODES.ERROR);
|
|
244
|
+
}
|
|
245
|
+
// Handle custom adapter command for testing
|
|
246
|
+
if (options.adapterCmd) {
|
|
247
|
+
const parts = options.adapterCmd.split(/\s+/);
|
|
248
|
+
const customAdapter = {
|
|
249
|
+
command: parts[0],
|
|
250
|
+
args: parts.slice(1),
|
|
251
|
+
description: 'Custom adapter via --adapter-cmd',
|
|
252
|
+
};
|
|
253
|
+
registerAdapter('custom', customAdapter);
|
|
254
|
+
options.adapter = 'custom';
|
|
255
|
+
}
|
|
256
|
+
// Resolve adapter
|
|
257
|
+
const adapter = resolveAdapter(options.adapter);
|
|
258
|
+
// Validate adapter package exists before proceeding
|
|
259
|
+
// Skip validation for custom adapters (--adapter-cmd) and non-npx adapters
|
|
260
|
+
if (!options.adapterCmd && adapter.command === 'npx' && adapter.args[0]) {
|
|
261
|
+
validateAdapter(adapter.args[0]);
|
|
262
|
+
}
|
|
263
|
+
// Add yolo flag to adapter args if needed
|
|
264
|
+
if (options.yolo && options.adapter === 'claude-code-acp') {
|
|
265
|
+
adapter.args = [...adapter.args, '--dangerously-skip-permissions'];
|
|
266
|
+
}
|
|
267
|
+
info(`Starting ralph loop (adapter=${options.adapter}, max ${maxLoops} iterations, ${maxRetries} retries, ${maxFailures} max failures)`);
|
|
268
|
+
if (options.focus) {
|
|
269
|
+
info(`Focus: ${options.focus}`);
|
|
270
|
+
}
|
|
271
|
+
// Initialize kspec context
|
|
272
|
+
const ctx = await initContext();
|
|
273
|
+
const specDir = ctx.specDir;
|
|
274
|
+
// Create session for event tracking
|
|
275
|
+
const sessionId = ulid();
|
|
276
|
+
await createSession(specDir, {
|
|
277
|
+
id: sessionId,
|
|
278
|
+
agent_type: options.adapter,
|
|
279
|
+
task_id: undefined, // Will be determined per iteration
|
|
280
|
+
});
|
|
281
|
+
// Log session start
|
|
282
|
+
await appendEvent(specDir, {
|
|
283
|
+
session_id: sessionId,
|
|
284
|
+
type: 'session.start',
|
|
285
|
+
data: {
|
|
286
|
+
adapter: options.adapter,
|
|
287
|
+
maxLoops,
|
|
288
|
+
maxRetries,
|
|
289
|
+
maxFailures,
|
|
290
|
+
yolo: options.yolo,
|
|
291
|
+
focus: options.focus,
|
|
292
|
+
},
|
|
293
|
+
});
|
|
294
|
+
let consecutiveFailures = 0;
|
|
295
|
+
let agent = null;
|
|
296
|
+
let acpSessionId = null;
|
|
297
|
+
// Create translator and renderer for this session
|
|
298
|
+
const translator = createTranslator();
|
|
299
|
+
const renderer = createCliRenderer();
|
|
300
|
+
try {
|
|
301
|
+
for (let iteration = 1; iteration <= maxLoops; iteration++) {
|
|
302
|
+
renderer.newSection?.(`Iteration ${iteration}/${maxLoops}`);
|
|
303
|
+
// Gather fresh context each iteration (only automation-eligible tasks)
|
|
304
|
+
// AC: @cli-ralph ac-16
|
|
305
|
+
const sessionCtx = await gatherSessionContext(ctx, { limit: '10', eligible: true });
|
|
306
|
+
// Check for ready tasks or active tasks
|
|
307
|
+
const hasActiveTasks = sessionCtx.active_tasks.length > 0;
|
|
308
|
+
const hasReadyTasks = sessionCtx.ready_tasks.length > 0;
|
|
309
|
+
if (!hasActiveTasks && !hasReadyTasks) {
|
|
310
|
+
info('No active or eligible ready tasks. Exiting loop.');
|
|
311
|
+
break;
|
|
312
|
+
}
|
|
313
|
+
// Build prompt
|
|
314
|
+
const prompt = buildPrompt(sessionCtx, iteration, maxLoops, options.focus);
|
|
315
|
+
if (options.dryRun) {
|
|
316
|
+
console.log(chalk.yellow('=== DRY RUN - Prompt that would be sent ===\n'));
|
|
317
|
+
console.log(prompt);
|
|
318
|
+
console.log(chalk.yellow('\n=== END DRY RUN ==='));
|
|
319
|
+
break;
|
|
320
|
+
}
|
|
321
|
+
// Log prompt
|
|
322
|
+
await appendEvent(specDir, {
|
|
323
|
+
session_id: sessionId,
|
|
324
|
+
type: 'prompt.sent',
|
|
325
|
+
data: {
|
|
326
|
+
iteration,
|
|
327
|
+
prompt,
|
|
328
|
+
tasks: {
|
|
329
|
+
active: sessionCtx.active_tasks.map(t => t.ref),
|
|
330
|
+
ready: sessionCtx.ready_tasks.map(t => t.ref),
|
|
331
|
+
},
|
|
332
|
+
},
|
|
333
|
+
});
|
|
334
|
+
// Retry loop for this iteration
|
|
335
|
+
let lastError = null;
|
|
336
|
+
let succeeded = false;
|
|
337
|
+
for (let attempt = 1; attempt <= maxRetries + 1; attempt++) {
|
|
338
|
+
if (attempt > 1) {
|
|
339
|
+
console.log(chalk.yellow(`\nRetry attempt ${attempt - 1}/${maxRetries}...`));
|
|
340
|
+
}
|
|
341
|
+
try {
|
|
342
|
+
// Spawn agent if not already running
|
|
343
|
+
if (!agent) {
|
|
344
|
+
info('Spawning ACP agent...');
|
|
345
|
+
agent = await spawnAndInitialize(adapter, {
|
|
346
|
+
cwd: process.cwd(),
|
|
347
|
+
clientOptions: {
|
|
348
|
+
clientInfo: {
|
|
349
|
+
name: 'kspec-ralph',
|
|
350
|
+
version: '0.1.0',
|
|
351
|
+
},
|
|
352
|
+
},
|
|
353
|
+
});
|
|
354
|
+
// Set up streaming update handler with translator + renderer
|
|
355
|
+
agent.client.on('update', (_sid, update) => {
|
|
356
|
+
// Translate ACP event to RalphEvent and render
|
|
357
|
+
const event = translator.translate(update);
|
|
358
|
+
if (event) {
|
|
359
|
+
renderer.render(event);
|
|
360
|
+
}
|
|
361
|
+
// Log raw update event (async, non-blocking)
|
|
362
|
+
appendEvent(specDir, {
|
|
363
|
+
session_id: sessionId,
|
|
364
|
+
type: 'session.update',
|
|
365
|
+
data: { iteration, update },
|
|
366
|
+
}).catch(() => {
|
|
367
|
+
// Ignore logging errors during streaming
|
|
368
|
+
});
|
|
369
|
+
});
|
|
370
|
+
// Set up tool request handler
|
|
371
|
+
agent.client.on('request', (reqId, method, params) => {
|
|
372
|
+
handleRequest(agent.client, reqId, method, params, options.yolo).catch((err) => {
|
|
373
|
+
agent.client.respondError(reqId, -32000, err.message);
|
|
374
|
+
});
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
// Create fresh ACP session per iteration to keep context clean
|
|
378
|
+
info('Creating ACP session...');
|
|
379
|
+
acpSessionId = await agent.client.newSession({
|
|
380
|
+
cwd: process.cwd(),
|
|
381
|
+
mcpServers: [], // No MCP servers for now
|
|
382
|
+
});
|
|
383
|
+
info('Sending prompt to agent...');
|
|
384
|
+
// Send prompt and wait for completion
|
|
385
|
+
const response = await agent.client.prompt({
|
|
386
|
+
sessionId: acpSessionId,
|
|
387
|
+
prompt: [{ type: 'text', text: prompt }],
|
|
388
|
+
});
|
|
389
|
+
// Log completion
|
|
390
|
+
await appendEvent(specDir, {
|
|
391
|
+
session_id: sessionId,
|
|
392
|
+
type: 'session.update',
|
|
393
|
+
data: {
|
|
394
|
+
iteration,
|
|
395
|
+
stopReason: response.stopReason,
|
|
396
|
+
completed: true,
|
|
397
|
+
},
|
|
398
|
+
});
|
|
399
|
+
// Check stop reason
|
|
400
|
+
if (response.stopReason === 'cancelled') {
|
|
401
|
+
throw new Error(errors.usage.agentPromptCancelled);
|
|
402
|
+
}
|
|
403
|
+
succeeded = true;
|
|
404
|
+
break;
|
|
405
|
+
}
|
|
406
|
+
catch (err) {
|
|
407
|
+
lastError = err;
|
|
408
|
+
error(errors.failures.iterationFailed(lastError.message));
|
|
409
|
+
// Clean up agent on error - will respawn next attempt
|
|
410
|
+
if (agent) {
|
|
411
|
+
agent.kill();
|
|
412
|
+
agent = null;
|
|
413
|
+
acpSessionId = null;
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
if (succeeded) {
|
|
418
|
+
console.log(); // Newline after streaming output
|
|
419
|
+
// Save session context snapshot for audit trail
|
|
420
|
+
await saveSessionContext(specDir, sessionId, iteration, sessionCtx);
|
|
421
|
+
success(`Completed iteration ${iteration}`);
|
|
422
|
+
consecutiveFailures = 0;
|
|
423
|
+
}
|
|
424
|
+
else {
|
|
425
|
+
consecutiveFailures++;
|
|
426
|
+
error(errors.failures.iterationFailedAfterRetries(iteration, maxRetries, consecutiveFailures, maxFailures));
|
|
427
|
+
if (lastError) {
|
|
428
|
+
error(errors.failures.lastError(lastError.message));
|
|
429
|
+
}
|
|
430
|
+
if (consecutiveFailures >= maxFailures) {
|
|
431
|
+
error(errors.failures.reachedMaxFailures(maxFailures));
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
info('Continuing to next iteration...');
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
finally {
|
|
439
|
+
// Clean up agent
|
|
440
|
+
if (agent) {
|
|
441
|
+
agent.kill();
|
|
442
|
+
}
|
|
443
|
+
// Log session end
|
|
444
|
+
const status = consecutiveFailures >= maxFailures ? 'abandoned' : 'completed';
|
|
445
|
+
await appendEvent(specDir, {
|
|
446
|
+
session_id: sessionId,
|
|
447
|
+
type: 'session.end',
|
|
448
|
+
data: {
|
|
449
|
+
status,
|
|
450
|
+
consecutiveFailures,
|
|
451
|
+
},
|
|
452
|
+
});
|
|
453
|
+
await updateSessionStatus(specDir, sessionId, status);
|
|
454
|
+
}
|
|
455
|
+
console.log(chalk.green(`\n${'─'.repeat(60)}`));
|
|
456
|
+
success('Ralph loop completed');
|
|
457
|
+
console.log(chalk.green(`${'─'.repeat(60)}\n`));
|
|
458
|
+
}
|
|
459
|
+
catch (err) {
|
|
460
|
+
error(errors.failures.ralphLoop, err);
|
|
461
|
+
process.exit(EXIT_CODES.ERROR);
|
|
462
|
+
}
|
|
463
|
+
});
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=ralph.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ralph.js","sourceRoot":"","sources":["../../../src/cli/commands/ralph.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.d.ts","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAmEpC;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAwF5D"}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
import chalk from 'chalk';
|
|
2
|
+
import { initContext, buildIndexes, } from '../../parser/index.js';
|
|
3
|
+
import { output, error } from '../output.js';
|
|
4
|
+
import { grepItem, formatMatchedFields } from '../../utils/grep.js';
|
|
5
|
+
import { errors } from '../../strings/index.js';
|
|
6
|
+
import { EXIT_CODES } from '../exit-codes.js';
|
|
7
|
+
/**
|
|
8
|
+
* Format a spec item for search results
|
|
9
|
+
*/
|
|
10
|
+
function formatSearchItem(item, matchedFields) {
|
|
11
|
+
const shortId = item._ulid.slice(0, 8);
|
|
12
|
+
const slugStr = item.slugs.length > 0 ? chalk.cyan(`@${item.slugs[0]}`) : '';
|
|
13
|
+
const typeStr = chalk.gray(`[${item.type}]`);
|
|
14
|
+
let status = '';
|
|
15
|
+
if (item.status && typeof item.status === 'object') {
|
|
16
|
+
const s = item.status;
|
|
17
|
+
if (s.implementation) {
|
|
18
|
+
const implColor = s.implementation === 'verified' ? chalk.green
|
|
19
|
+
: s.implementation === 'implemented' ? chalk.cyan
|
|
20
|
+
: s.implementation === 'in_progress' ? chalk.yellow
|
|
21
|
+
: chalk.gray;
|
|
22
|
+
status = implColor(s.implementation);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
let line = `${chalk.gray(shortId)} ${typeStr} ${item.title}`;
|
|
26
|
+
if (slugStr)
|
|
27
|
+
line += ` ${slugStr}`;
|
|
28
|
+
if (status)
|
|
29
|
+
line += ` ${status}`;
|
|
30
|
+
console.log(line);
|
|
31
|
+
console.log(chalk.gray(` matched: ${formatMatchedFields(matchedFields)}`));
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Format a task for search results
|
|
35
|
+
*/
|
|
36
|
+
function formatSearchTask(task, matchedFields) {
|
|
37
|
+
const shortId = task._ulid.slice(0, 8);
|
|
38
|
+
const slugStr = task.slugs.length > 0 ? chalk.cyan(`@${task.slugs[0]}`) : '';
|
|
39
|
+
const statusColor = task.status === 'completed' ? chalk.green
|
|
40
|
+
: task.status === 'in_progress' ? chalk.blue
|
|
41
|
+
: task.status === 'blocked' ? chalk.red
|
|
42
|
+
: chalk.gray;
|
|
43
|
+
const priority = task.priority <= 2 ? chalk.red(`P${task.priority}`) : chalk.gray(`P${task.priority}`);
|
|
44
|
+
let line = `${chalk.gray(shortId)} ${statusColor(`[${task.status}]`)} ${priority} ${task.title}`;
|
|
45
|
+
if (slugStr)
|
|
46
|
+
line += ` ${slugStr}`;
|
|
47
|
+
console.log(line);
|
|
48
|
+
console.log(chalk.gray(` matched: ${formatMatchedFields(matchedFields)}`));
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Register the search command
|
|
52
|
+
*/
|
|
53
|
+
export function registerSearchCommand(program) {
|
|
54
|
+
program
|
|
55
|
+
.command('search <pattern>')
|
|
56
|
+
.description('Search across all items and tasks with regex pattern')
|
|
57
|
+
.option('-t, --type <type>', 'Filter by item type')
|
|
58
|
+
.option('-s, --status <status>', 'Filter by task status')
|
|
59
|
+
.option('--items-only', 'Search only spec items')
|
|
60
|
+
.option('--tasks-only', 'Search only tasks')
|
|
61
|
+
.option('--limit <n>', 'Limit results', '50')
|
|
62
|
+
.action(async (pattern, options) => {
|
|
63
|
+
try {
|
|
64
|
+
const ctx = await initContext();
|
|
65
|
+
const { itemIndex, tasks, items, refIndex } = await buildIndexes(ctx);
|
|
66
|
+
const results = [];
|
|
67
|
+
const limit = parseInt(options.limit, 10) || 50;
|
|
68
|
+
// Search spec items
|
|
69
|
+
if (!options.tasksOnly) {
|
|
70
|
+
for (const item of items) {
|
|
71
|
+
// Apply type filter
|
|
72
|
+
if (options.type && item.type !== options.type)
|
|
73
|
+
continue;
|
|
74
|
+
const match = grepItem(item, pattern);
|
|
75
|
+
if (match) {
|
|
76
|
+
results.push({
|
|
77
|
+
type: 'item',
|
|
78
|
+
item,
|
|
79
|
+
matchedFields: match.matchedFields,
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
// Search tasks
|
|
85
|
+
if (!options.itemsOnly) {
|
|
86
|
+
for (const task of tasks) {
|
|
87
|
+
// Apply status filter
|
|
88
|
+
if (options.status && task.status !== options.status)
|
|
89
|
+
continue;
|
|
90
|
+
const match = grepItem(task, pattern);
|
|
91
|
+
if (match) {
|
|
92
|
+
results.push({
|
|
93
|
+
type: 'task',
|
|
94
|
+
item: task,
|
|
95
|
+
matchedFields: match.matchedFields,
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Limit results
|
|
101
|
+
const limitedResults = results.slice(0, limit);
|
|
102
|
+
output({
|
|
103
|
+
pattern,
|
|
104
|
+
results: limitedResults.map(r => ({
|
|
105
|
+
type: r.type,
|
|
106
|
+
ulid: r.item._ulid,
|
|
107
|
+
title: r.item.title,
|
|
108
|
+
matchedFields: r.matchedFields,
|
|
109
|
+
})),
|
|
110
|
+
total: results.length,
|
|
111
|
+
showing: limitedResults.length,
|
|
112
|
+
}, () => {
|
|
113
|
+
if (limitedResults.length === 0) {
|
|
114
|
+
console.log(chalk.gray(`No matches found for "${pattern}"`));
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
for (const result of limitedResults) {
|
|
118
|
+
if (result.type === 'item') {
|
|
119
|
+
formatSearchItem(result.item, result.matchedFields);
|
|
120
|
+
}
|
|
121
|
+
else {
|
|
122
|
+
formatSearchTask(result.item, result.matchedFields);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
console.log(chalk.gray(`\n${limitedResults.length} result(s)${results.length > limit ? ` (showing first ${limit})` : ''}`));
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
catch (err) {
|
|
129
|
+
error(errors.failures.search, err);
|
|
130
|
+
process.exit(EXIT_CODES.ERROR);
|
|
131
|
+
}
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
//# sourceMappingURL=search.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"search.js","sourceRoot":"","sources":["../../../src/cli/commands/search.ts"],"names":[],"mappings":"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"}
|