@kosuke-ai/cli 0.0.6 ā 0.0.8
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 +76 -18
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +58 -26
- package/dist/index.js.map +1 -1
- package/dist/kosuke/commands/analyse.d.ts +1 -1
- package/dist/kosuke/commands/analyse.d.ts.map +1 -1
- package/dist/kosuke/commands/analyse.js +124 -180
- package/dist/kosuke/commands/analyse.js.map +1 -1
- package/dist/kosuke/commands/lint.d.ts +1 -5
- package/dist/kosuke/commands/lint.d.ts.map +1 -1
- package/dist/kosuke/commands/lint.js +78 -97
- package/dist/kosuke/commands/lint.js.map +1 -1
- package/dist/kosuke/commands/requirements.d.ts +15 -0
- package/dist/kosuke/commands/requirements.d.ts.map +1 -0
- package/dist/kosuke/commands/requirements.js +286 -0
- package/dist/kosuke/commands/requirements.js.map +1 -0
- package/dist/kosuke/commands/sync-rules.d.ts +2 -1
- package/dist/kosuke/commands/sync-rules.d.ts.map +1 -1
- package/dist/kosuke/commands/sync-rules.js +106 -102
- package/dist/kosuke/commands/sync-rules.js.map +1 -1
- package/dist/kosuke/types.d.ts +11 -1
- package/dist/kosuke/types.d.ts.map +1 -1
- package/dist/kosuke/utils/git.d.ts +0 -4
- package/dist/kosuke/utils/git.d.ts.map +1 -1
- package/dist/kosuke/utils/git.js +0 -6
- package/dist/kosuke/utils/git.js.map +1 -1
- package/dist/kosuke/utils/pr-orchestrator.d.ts +47 -0
- package/dist/kosuke/utils/pr-orchestrator.d.ts.map +1 -0
- package/dist/kosuke/utils/pr-orchestrator.js +152 -0
- package/dist/kosuke/utils/pr-orchestrator.js.map +1 -0
- package/package.json +4 -2
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../../kosuke/commands/lint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAgB,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"lint.js","sourceRoot":"","sources":["../../../kosuke/commands/lint.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,KAAK,EAAgB,MAAM,gCAAgC,CAAC;AACrE,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AASxD;;GAEG;AACH,KAAK,UAAU,aAAa,CAAC,UAAkB;IAC7C,OAAO,CAAC,GAAG,CAAC,8CAA8C,CAAC,CAAC;IAE5D,MAAM,aAAa,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC;IAEpC,gBAAgB;IAChB,MAAM,YAAY,GAAG;;;;uGAIgF,CAAC;IAEtG,cAAc;IACd,MAAM,UAAU,GAAG;;;EAGnB,UAAU;;;;;;;;;;mEAUuD,CAAC;IAElE,MAAM,OAAO,GAAY;QACvB,KAAK,EAAE,mBAAmB;QAC1B,YAAY;QACZ,QAAQ,EAAE,EAAE;QACZ,GAAG,EAAE,aAAa;QAClB,cAAc,EAAE,mBAAmB;KACpC,CAAC;IAEF,IAAI,CAAC;QACH,MAAM,cAAc,GAAG,KAAK,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,CAAC,CAAC;QAE9D,IAAI,QAAQ,GAAG,CAAC,CAAC;QAEjB,2BAA2B;QAC3B,IAAI,KAAK,EAAE,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YAC3C,IAAI,OAAO,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gBACjC,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,OAAO,CAAC;gBACxC,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;oBAC5B,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;wBAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;wBAC/B,oBAAoB;wBACpB,IACE,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC;4BACpB,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC;4BACtB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC;4BAClB,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,EAClB,CAAC;4BACD,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;wBAC/B,CAAC;oBACH,CAAC;yBAAM,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;wBACrC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;4BAC9D,QAAQ,EAAE,CAAC;4BACX,OAAO,CAAC,GAAG,CAAC,sBAAsB,QAAQ,KAAK,CAAC,CAAC;wBACnD,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,CAAC,GAAG,CAAC,yBAAyB,QAAQ,iBAAiB,CAAC,CAAC;QAChE,OAAO,QAAQ,GAAG,CAAC,CAAC;IACtB,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,iCAAiC,EAAE,KAAK,CAAC,CAAC;QACxD,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;GAEG;AACH,KAAK,UAAU,iBAAiB;IAC9B,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,IAAI,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;IAEjC,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;QACvB,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAC3D,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE,CAAC;IACzD,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;IACzC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAE9B,8CAA8C;IAC9C,IAAI,YAAY,GAAG,CAAC,CAAC;IACrB,MAAM,WAAW,GAAG,CAAC,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,CAAC;IAEnB,OAAO,CAAC,UAAU,CAAC,OAAO,IAAI,YAAY,GAAG,WAAW,EAAE,CAAC;QACzD,YAAY,EAAE,CAAC;QACf,OAAO,CAAC,GAAG,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,kBAAkB,YAAY,IAAI,WAAW,EAAE,CAAC,CAAC;QAC7D,OAAO,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC;QAEjC,MAAM,UAAU,GAAG,MAAM,aAAa,CAAC,UAAU,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QAE/D,IAAI,CAAC,UAAU,EAAE,CAAC;YAChB,OAAO,CAAC,GAAG,CAAC,uCAAuC,CAAC,CAAC;YACrD,MAAM;QACR,CAAC;QAED,UAAU,EAAE,CAAC;QAEb,qCAAqC;QACrC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;QACzC,UAAU,GAAG,MAAM,OAAO,EAAE,CAAC;QAE7B,IAAI,UAAU,CAAC,OAAO,EAAE,CAAC;YACvB,OAAO,CAAC,GAAG,CAAC,+BAA+B,CAAC,CAAC;YAC7C,MAAM;QACR,CAAC;aAAM,CAAC;YACN,OAAO,CAAC,GAAG,CAAC,6BAA6B,UAAU,CAAC,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,CAAC;YAC9F,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAChC,CAAC;IACH,CAAC;IAED,qBAAqB;IACrB,IAAI,CAAC,UAAU,CAAC,OAAO,EAAE,CAAC;QACxB,OAAO,CAAC,KAAK,CAAC,uDAAuD,CAAC,CAAC;QACvE,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,CAAC;QACnC,OAAO,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;QAC9B,MAAM,IAAI,KAAK,CAAC,8CAA8C,CAAC,CAAC;IAClE,CAAC;IAED,OAAO;QACL,OAAO,EAAE,IAAI;QACb,QAAQ,EAAE,YAAY;QACtB,YAAY,EAAE,UAAU;KACzB,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,UAAuB,EAAE;IACzD,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC,CAAC;IAEhD,IAAI,CAAC;QACH,uBAAuB;QACvB,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,EAAE,CAAC;YACnC,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;QACxE,CAAC;QAED,kDAAkD;QAClD,IAAI,OAAO,CAAC,EAAE,EAAE,CAAC;YACf,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,MAAM,SAAS,CACxC;gBACE,YAAY,EAAE,iBAAiB;gBAC/B,UAAU,EAAE,OAAO,CAAC,UAAU;gBAC9B,aAAa,EAAE,2BAA2B;gBAC1C,OAAO,EAAE,2BAA2B;gBACpC,MAAM,EAAE;;;;;;;;;;;;oDAYkC;aAC3C,EACD,iBAAiB,CAClB,CAAC;YAEF,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,UAAU,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;QACxC,CAAC;aAAM,CAAC;YACN,4BAA4B;YAC5B,MAAM,MAAM,GAAG,MAAM,iBAAiB,EAAE,CAAC;YAEzC,OAAO,CAAC,GAAG,CAAC,2BAA2B,CAAC,CAAC;YACzC,OAAO,CAAC,GAAG,CAAC,gBAAgB,MAAM,CAAC,QAAQ,EAAE,CAAC,CAAC;YAC/C,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;YACxD,OAAO,CAAC,GAAG,CAAC,wEAAwE,CAAC,CAAC;QACxF,CAAC;IACH,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,OAAO,CAAC,KAAK,CAAC,yBAAyB,EAAE,KAAK,CAAC,CAAC;QAChD,MAAM,KAAK,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements command - Interactive requirements gathering with Claude AI
|
|
3
|
+
*
|
|
4
|
+
* Strategy: Multi-turn conversation to build comprehensive requirements
|
|
5
|
+
* - User provides product description
|
|
6
|
+
* - Claude analyzes and extracts functionalities
|
|
7
|
+
* - Claude asks clarification questions
|
|
8
|
+
* - User answers questions (iterative until clear)
|
|
9
|
+
* - Generate docs.md with complete requirements
|
|
10
|
+
*/
|
|
11
|
+
/**
|
|
12
|
+
* Main requirements command
|
|
13
|
+
*/
|
|
14
|
+
export declare function requirementsCommand(): Promise<void>;
|
|
15
|
+
//# sourceMappingURL=requirements.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.d.ts","sourceRoot":"","sources":["../../../kosuke/commands/requirements.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AA8VH;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAazD"}
|
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Requirements command - Interactive requirements gathering with Claude AI
|
|
3
|
+
*
|
|
4
|
+
* Strategy: Multi-turn conversation to build comprehensive requirements
|
|
5
|
+
* - User provides product description
|
|
6
|
+
* - Claude analyzes and extracts functionalities
|
|
7
|
+
* - Claude asks clarification questions
|
|
8
|
+
* - User answers questions (iterative until clear)
|
|
9
|
+
* - Generate docs.md with complete requirements
|
|
10
|
+
*/
|
|
11
|
+
import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
12
|
+
import * as readline from 'readline';
|
|
13
|
+
import { join } from 'path';
|
|
14
|
+
/**
|
|
15
|
+
* Calculate cost based on Claude Sonnet 4.5 pricing
|
|
16
|
+
* - $3 per million input tokens
|
|
17
|
+
* - $15 per million output tokens
|
|
18
|
+
* - $3.75 per million cache creation tokens
|
|
19
|
+
* - $0.30 per million cache read tokens
|
|
20
|
+
*/
|
|
21
|
+
function calculateCost(inputTokens, outputTokens, cacheCreationTokens = 0, cacheReadTokens = 0) {
|
|
22
|
+
const INPUT_COST_PER_MILLION = 3.0;
|
|
23
|
+
const OUTPUT_COST_PER_MILLION = 15.0;
|
|
24
|
+
const CACHE_CREATION_COST_PER_MILLION = 3.75;
|
|
25
|
+
const CACHE_READ_COST_PER_MILLION = 0.3;
|
|
26
|
+
const inputCost = (inputTokens / 1000000) * INPUT_COST_PER_MILLION;
|
|
27
|
+
const outputCost = (outputTokens / 1000000) * OUTPUT_COST_PER_MILLION;
|
|
28
|
+
const cacheCreationCost = (cacheCreationTokens / 1000000) * CACHE_CREATION_COST_PER_MILLION;
|
|
29
|
+
const cacheReadCost = (cacheReadTokens / 1000000) * CACHE_READ_COST_PER_MILLION;
|
|
30
|
+
return inputCost + outputCost + cacheCreationCost + cacheReadCost;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Format token usage for display
|
|
34
|
+
*/
|
|
35
|
+
function formatTokenUsage(inputTokens, outputTokens, cacheCreationTokens, cacheReadTokens, cost) {
|
|
36
|
+
const breakdown = [];
|
|
37
|
+
if (inputTokens > 0)
|
|
38
|
+
breakdown.push(`${inputTokens.toLocaleString()} input`);
|
|
39
|
+
if (outputTokens > 0)
|
|
40
|
+
breakdown.push(`${outputTokens.toLocaleString()} output`);
|
|
41
|
+
if (cacheCreationTokens > 0)
|
|
42
|
+
breakdown.push(`${cacheCreationTokens.toLocaleString()} cache write`);
|
|
43
|
+
if (cacheReadTokens > 0)
|
|
44
|
+
breakdown.push(`${cacheReadTokens.toLocaleString()} cache read`);
|
|
45
|
+
return `š° Cost: $${cost.toFixed(4)} (${breakdown.join(' + ')} tokens)`;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Process a single Claude interaction
|
|
49
|
+
*/
|
|
50
|
+
async function processClaudeInteraction(userInput, sessionId, isFirstRequest) {
|
|
51
|
+
const workspaceRoot = process.cwd();
|
|
52
|
+
// Modify the prompt for the first request to enforce planning workflow
|
|
53
|
+
let effectivePrompt = userInput;
|
|
54
|
+
if (isFirstRequest) {
|
|
55
|
+
effectivePrompt = `${userInput}
|
|
56
|
+
|
|
57
|
+
IMPORTANT INSTRUCTIONS FOR FIRST REQUEST:
|
|
58
|
+
This is a web application product implementation request. You MUST follow this workflow:
|
|
59
|
+
|
|
60
|
+
1. **Analyze the Request**: Understand what product needs to be built
|
|
61
|
+
2. **List Core Functionalities**: Present all features in clear bullet points
|
|
62
|
+
3. **Define Implementation Plan**: Create a detailed plan with all required components
|
|
63
|
+
4. **Ask NUMBERED Clarification Questions**: List any ambiguities or missing requirements with numbers
|
|
64
|
+
|
|
65
|
+
Format your response as:
|
|
66
|
+
---
|
|
67
|
+
## Product Analysis
|
|
68
|
+
[Brief description of what will be built]
|
|
69
|
+
|
|
70
|
+
## Core Functionalities
|
|
71
|
+
- [Functionality 1]
|
|
72
|
+
- [Functionality 2]
|
|
73
|
+
- [Functionality 3]
|
|
74
|
+
...
|
|
75
|
+
|
|
76
|
+
## Implementation Plan
|
|
77
|
+
[High-level technical approach and architecture]
|
|
78
|
+
|
|
79
|
+
## Clarification Questions
|
|
80
|
+
1. [Question 1]
|
|
81
|
+
2. [Question 2]
|
|
82
|
+
3. [Question 3]
|
|
83
|
+
...
|
|
84
|
+
|
|
85
|
+
---
|
|
86
|
+
|
|
87
|
+
WORKFLOW AFTER USER ANSWERS QUESTIONS:
|
|
88
|
+
When the user has answered all questions and requirements are clear, create a comprehensive requirements document in docs.md with:
|
|
89
|
+
- Product Overview
|
|
90
|
+
- Core Functionalities (detailed)
|
|
91
|
+
- Technical Architecture
|
|
92
|
+
- User Flows
|
|
93
|
+
- Database Schema
|
|
94
|
+
- API Endpoints
|
|
95
|
+
- Implementation Notes
|
|
96
|
+
|
|
97
|
+
IMPORTANT: This is an INTERACTIVE conversation. After showing this plan, WAIT for the user's response. The conversation continues - do NOT stop the chat loop.`;
|
|
98
|
+
}
|
|
99
|
+
const options = {
|
|
100
|
+
model: 'claude-sonnet-4-5',
|
|
101
|
+
maxTurns: 20,
|
|
102
|
+
cwd: workspaceRoot,
|
|
103
|
+
permissionMode: 'acceptEdits',
|
|
104
|
+
resume: sessionId || undefined,
|
|
105
|
+
allowedTools: ['Read', 'Write', 'Edit', 'LS', 'Grep', 'Glob', 'WebSearch'],
|
|
106
|
+
systemPrompt: {
|
|
107
|
+
type: 'preset',
|
|
108
|
+
preset: 'claude_code',
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
const responseStream = query({ prompt: effectivePrompt, options });
|
|
112
|
+
let responseText = '';
|
|
113
|
+
let newSessionId = sessionId || '';
|
|
114
|
+
let inputTokens = 0;
|
|
115
|
+
let outputTokens = 0;
|
|
116
|
+
let cacheCreationTokens = 0;
|
|
117
|
+
let cacheReadTokens = 0;
|
|
118
|
+
// Process the async generator
|
|
119
|
+
for await (const message of responseStream) {
|
|
120
|
+
if (message.type === 'user') {
|
|
121
|
+
if (!newSessionId) {
|
|
122
|
+
newSessionId = message.session_id;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
else if (message.type === 'assistant') {
|
|
126
|
+
const content = message.message.content;
|
|
127
|
+
for (const block of content) {
|
|
128
|
+
if (block.type === 'text') {
|
|
129
|
+
responseText += block.text;
|
|
130
|
+
}
|
|
131
|
+
else if (block.type === 'tool_use') {
|
|
132
|
+
// Show tool usage
|
|
133
|
+
if (block.name === 'Write' || block.name === 'Edit') {
|
|
134
|
+
const input = block.input;
|
|
135
|
+
if (input.path === 'docs.md' || input.path?.includes('docs.md')) {
|
|
136
|
+
console.log('\nāļø Generating docs.md...');
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
else if (message.type === 'result' && message.subtype === 'success') {
|
|
143
|
+
// Track token usage
|
|
144
|
+
if (message.usage) {
|
|
145
|
+
inputTokens += message.usage.input_tokens || 0;
|
|
146
|
+
outputTokens += message.usage.output_tokens || 0;
|
|
147
|
+
cacheCreationTokens += message.usage.cache_creation_input_tokens || 0;
|
|
148
|
+
cacheReadTokens += message.usage.cache_read_input_tokens || 0;
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
return {
|
|
153
|
+
response: responseText,
|
|
154
|
+
sessionId: newSessionId,
|
|
155
|
+
inputTokens,
|
|
156
|
+
outputTokens,
|
|
157
|
+
cacheCreationTokens,
|
|
158
|
+
cacheReadTokens,
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
/**
|
|
162
|
+
* Interactive requirements gathering loop
|
|
163
|
+
*/
|
|
164
|
+
async function interactiveSession() {
|
|
165
|
+
console.log(`\n${'ā'.repeat(63)}`);
|
|
166
|
+
console.log('ā Kosuke Requirements - Interactive Requirements Tool ā');
|
|
167
|
+
console.log(`${'ā'.repeat(63)}\n`);
|
|
168
|
+
console.log('š” This tool will help you create comprehensive product requirements.\n');
|
|
169
|
+
console.log("š I'll analyze your product idea, ask clarification questions,");
|
|
170
|
+
console.log(' and generate a detailed docs.md file.\n');
|
|
171
|
+
const rl = readline.createInterface({
|
|
172
|
+
input: process.stdin,
|
|
173
|
+
output: process.stdout,
|
|
174
|
+
});
|
|
175
|
+
const session = {
|
|
176
|
+
productDescription: '',
|
|
177
|
+
conversationHistory: [],
|
|
178
|
+
isFirstRequest: true,
|
|
179
|
+
};
|
|
180
|
+
let sessionId = null;
|
|
181
|
+
let totalInputTokens = 0;
|
|
182
|
+
let totalOutputTokens = 0;
|
|
183
|
+
let totalCacheCreationTokens = 0;
|
|
184
|
+
let totalCacheReadTokens = 0;
|
|
185
|
+
let totalCost = 0;
|
|
186
|
+
const askQuestion = (prompt) => {
|
|
187
|
+
return new Promise((resolve) => {
|
|
188
|
+
rl.question(prompt, (answer) => {
|
|
189
|
+
resolve(answer.trim());
|
|
190
|
+
});
|
|
191
|
+
});
|
|
192
|
+
};
|
|
193
|
+
try {
|
|
194
|
+
// Initial product description
|
|
195
|
+
console.log("š Let's start! Describe the web application you want to build:\n");
|
|
196
|
+
const productDescription = await askQuestion('You: ');
|
|
197
|
+
if (!productDescription) {
|
|
198
|
+
console.log('\nā No product description provided. Exiting.');
|
|
199
|
+
rl.close();
|
|
200
|
+
return;
|
|
201
|
+
}
|
|
202
|
+
session.productDescription = productDescription;
|
|
203
|
+
session.conversationHistory.push(`User: ${productDescription}`);
|
|
204
|
+
// Main conversation loop
|
|
205
|
+
let continueConversation = true;
|
|
206
|
+
while (continueConversation) {
|
|
207
|
+
console.log('\nš¤ Claude is thinking...\n');
|
|
208
|
+
// Get Claude's response
|
|
209
|
+
const result = await processClaudeInteraction(session.isFirstRequest
|
|
210
|
+
? productDescription
|
|
211
|
+
: session.conversationHistory[session.conversationHistory.length - 1].replace('User: ', ''), sessionId, session.isFirstRequest);
|
|
212
|
+
sessionId = result.sessionId;
|
|
213
|
+
session.isFirstRequest = false;
|
|
214
|
+
// Track costs
|
|
215
|
+
totalInputTokens += result.inputTokens;
|
|
216
|
+
totalOutputTokens += result.outputTokens;
|
|
217
|
+
totalCacheCreationTokens += result.cacheCreationTokens;
|
|
218
|
+
totalCacheReadTokens += result.cacheReadTokens;
|
|
219
|
+
const batchCost = calculateCost(result.inputTokens, result.outputTokens, result.cacheCreationTokens, result.cacheReadTokens);
|
|
220
|
+
totalCost += batchCost;
|
|
221
|
+
// Display Claude's response
|
|
222
|
+
console.log('Claude:\n');
|
|
223
|
+
console.log(result.response);
|
|
224
|
+
console.log('\n' + 'ā'.repeat(60));
|
|
225
|
+
console.log(formatTokenUsage(result.inputTokens, result.outputTokens, result.cacheCreationTokens, result.cacheReadTokens, batchCost));
|
|
226
|
+
console.log('ā'.repeat(60) + '\n');
|
|
227
|
+
session.conversationHistory.push(`Claude: ${result.response}`);
|
|
228
|
+
// Check if docs.md was created
|
|
229
|
+
const docsPath = join(process.cwd(), 'docs.md');
|
|
230
|
+
try {
|
|
231
|
+
const fs = await import('fs');
|
|
232
|
+
if (fs.existsSync(docsPath)) {
|
|
233
|
+
console.log('\nā
Requirements document created: docs.md');
|
|
234
|
+
console.log('\nš Total Session Cost:');
|
|
235
|
+
console.log(formatTokenUsage(totalInputTokens, totalOutputTokens, totalCacheCreationTokens, totalCacheReadTokens, totalCost));
|
|
236
|
+
console.log('\nš Requirements gathering complete!\n');
|
|
237
|
+
continueConversation = false;
|
|
238
|
+
break;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
catch {
|
|
242
|
+
// docs.md not yet created, continue conversation
|
|
243
|
+
}
|
|
244
|
+
// Ask for user response
|
|
245
|
+
console.log('š¬ Your response (or type "exit" to quit):\n');
|
|
246
|
+
const userResponse = await askQuestion('You: ');
|
|
247
|
+
if (!userResponse) {
|
|
248
|
+
console.log('\nā ļø Empty response. Please provide an answer or type "exit".');
|
|
249
|
+
continue;
|
|
250
|
+
}
|
|
251
|
+
if (userResponse.toLowerCase() === 'exit') {
|
|
252
|
+
console.log('\nš Exiting requirements gathering.\n');
|
|
253
|
+
console.log('š Session Cost:');
|
|
254
|
+
console.log(formatTokenUsage(totalInputTokens, totalOutputTokens, totalCacheCreationTokens, totalCacheReadTokens, totalCost));
|
|
255
|
+
continueConversation = false;
|
|
256
|
+
break;
|
|
257
|
+
}
|
|
258
|
+
session.conversationHistory.push(`User: ${userResponse}`);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
catch (error) {
|
|
262
|
+
console.error('\nā Error during requirements gathering:', error);
|
|
263
|
+
throw error;
|
|
264
|
+
}
|
|
265
|
+
finally {
|
|
266
|
+
rl.close();
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
/**
|
|
270
|
+
* Main requirements command
|
|
271
|
+
*/
|
|
272
|
+
export async function requirementsCommand() {
|
|
273
|
+
try {
|
|
274
|
+
// Validate environment
|
|
275
|
+
if (!process.env.ANTHROPIC_API_KEY) {
|
|
276
|
+
throw new Error('ANTHROPIC_API_KEY environment variable is required');
|
|
277
|
+
}
|
|
278
|
+
// Start interactive session
|
|
279
|
+
await interactiveSession();
|
|
280
|
+
}
|
|
281
|
+
catch (error) {
|
|
282
|
+
console.error('\nā Requirements command failed:', error);
|
|
283
|
+
throw error;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
//# sourceMappingURL=requirements.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"requirements.js","sourceRoot":"","sources":["../../../kosuke/commands/requirements.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Sync rules command - Syncs rules and documentation from kosuke-template
|
|
3
3
|
*/
|
|
4
|
+
import type { SyncRulesOptions } from '../types.js';
|
|
4
5
|
/**
|
|
5
6
|
* Main sync-rules command
|
|
6
7
|
*/
|
|
7
|
-
export declare function syncRulesCommand(
|
|
8
|
+
export declare function syncRulesCommand(options?: SyncRulesOptions): Promise<void>;
|
|
8
9
|
//# sourceMappingURL=sync-rules.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sync-rules.d.ts","sourceRoot":"","sources":["../../../kosuke/commands/sync-rules.ts"],"names":[],"mappings":"AAAA;;GAEG;
|
|
1
|
+
{"version":3,"file":"sync-rules.d.ts","sourceRoot":"","sources":["../../../kosuke/commands/sync-rules.ts"],"names":[],"mappings":"AAAA;;GAEG;AASH,OAAO,KAAK,EAAmB,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAqUrE;;GAEG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CA4FpF"}
|
|
@@ -5,14 +5,13 @@ import { query } from '@anthropic-ai/claude-agent-sdk';
|
|
|
5
5
|
import simpleGit from 'simple-git';
|
|
6
6
|
import { readFileSync, writeFileSync, existsSync, mkdirSync, rmSync } from 'fs';
|
|
7
7
|
import { join, dirname } from 'path';
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
8
|
+
import { isKosukeTemplateRepo } from '../utils/git.js';
|
|
9
|
+
import { runWithPR } from '../utils/pr-orchestrator.js';
|
|
10
10
|
import { runFormat, runLint } from '../utils/validator.js';
|
|
11
11
|
// Constants
|
|
12
12
|
const KOSUKE_TEMPLATE_REPO = 'https://github.com/Kosuke-Org/kosuke-template.git';
|
|
13
13
|
const KOSUKE_TEMPLATE_BRANCH = 'main';
|
|
14
14
|
const TEMP_DIR = '.tmp/kosuke-template';
|
|
15
|
-
const TARGET_BRANCH = 'main';
|
|
16
15
|
const RULES_FILE = '.cursor/rules/general.mdc';
|
|
17
16
|
const CLAUDE_MD_FILE = 'CLAUDE.md';
|
|
18
17
|
/**
|
|
@@ -207,35 +206,56 @@ Keep it concise and developer-friendly. Use bullet points starting with emojis.`
|
|
|
207
206
|
}
|
|
208
207
|
}
|
|
209
208
|
/**
|
|
210
|
-
*
|
|
209
|
+
* Core sync logic (git-agnostic)
|
|
211
210
|
*/
|
|
212
|
-
async function
|
|
213
|
-
|
|
214
|
-
const git =
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
const branchName = `sync/rules-${timestamp}`;
|
|
218
|
-
console.log(`šæ Creating branch: ${branchName}`);
|
|
219
|
-
// Create and checkout new branch
|
|
220
|
-
await git.checkout(TARGET_BRANCH);
|
|
221
|
-
await git.pull('origin', TARGET_BRANCH);
|
|
222
|
-
// Check if branch already exists locally and delete it
|
|
223
|
-
try {
|
|
224
|
-
const branches = await git.branchLocal();
|
|
225
|
-
if (branches.all.includes(branchName)) {
|
|
226
|
-
console.log(` Deleting existing local branch: ${branchName}`);
|
|
227
|
-
await git.deleteLocalBranch(branchName, true);
|
|
228
|
-
}
|
|
211
|
+
async function syncRulesCore(force) {
|
|
212
|
+
// Clone/update kosuke-template
|
|
213
|
+
const git = await cloneOrUpdateKosukeTemplate();
|
|
214
|
+
if (force) {
|
|
215
|
+
console.log('ā” Force mode: Comparing rules file...\n');
|
|
229
216
|
}
|
|
230
|
-
|
|
231
|
-
//
|
|
217
|
+
else {
|
|
218
|
+
// Check if rules file changed in last 24 hours
|
|
219
|
+
console.log('š
Checking for changes in last 24 hours...');
|
|
220
|
+
const hasChanges = await checkRulesChangedInLast24Hours(git);
|
|
221
|
+
if (!hasChanges) {
|
|
222
|
+
console.log('ā
No changes to rules in last 24 hours. Nothing to sync.');
|
|
223
|
+
console.log(' Use --force flag to compare files regardless of recent commits.');
|
|
224
|
+
throw new Error('No recent changes');
|
|
225
|
+
}
|
|
226
|
+
console.log(` ā
Found changes in ${RULES_FILE}\n`);
|
|
232
227
|
}
|
|
233
|
-
|
|
234
|
-
// Write adapted content to files
|
|
228
|
+
// Read current repository versions
|
|
235
229
|
const workspaceRoot = process.cwd();
|
|
230
|
+
const kosukeFile = join(TEMP_DIR, RULES_FILE);
|
|
231
|
+
const currentFile = join(workspaceRoot, RULES_FILE);
|
|
232
|
+
if (!existsSync(kosukeFile)) {
|
|
233
|
+
throw new Error(`${RULES_FILE} not found in kosuke-template`);
|
|
234
|
+
}
|
|
235
|
+
const kosukeContent = readFileSync(kosukeFile, 'utf-8');
|
|
236
|
+
const currentContent = existsSync(currentFile) ? readFileSync(currentFile, 'utf-8') : '';
|
|
237
|
+
// Check if content is actually different
|
|
238
|
+
if (kosukeContent === currentContent) {
|
|
239
|
+
console.log(`ā¹ļø No differences detected in ${RULES_FILE}. Nothing to sync.`);
|
|
240
|
+
throw new Error('No differences detected');
|
|
241
|
+
}
|
|
242
|
+
console.log(`š„ Processing ${RULES_FILE}...`);
|
|
243
|
+
const adaptation = await adaptRulesWithClaude(RULES_FILE, currentContent);
|
|
244
|
+
// Abort if no changes
|
|
245
|
+
if (!adaptation.relevant) {
|
|
246
|
+
console.log('ā
No relevant changes to sync. Aborting.');
|
|
247
|
+
throw new Error('No relevant changes');
|
|
248
|
+
}
|
|
249
|
+
// Generate CLAUDE.md from adapted general.mdc
|
|
250
|
+
console.log(`\nš Generating ${CLAUDE_MD_FILE} from ${RULES_FILE}...`);
|
|
251
|
+
const claudeMdContent = generateClaudeMd(adaptation.adaptedContent);
|
|
252
|
+
// Generate LLM summary of changes
|
|
253
|
+
const changesSummary = await generateChangesSummary(currentContent, adaptation.adaptedContent);
|
|
254
|
+
// Write files locally
|
|
255
|
+
const workspaceRootPath = process.cwd();
|
|
236
256
|
console.log('š Writing adapted files...');
|
|
237
257
|
// Write general.mdc
|
|
238
|
-
const rulesFile = join(
|
|
258
|
+
const rulesFile = join(workspaceRootPath, RULES_FILE);
|
|
239
259
|
const rulesDir = dirname(rulesFile);
|
|
240
260
|
if (!existsSync(rulesDir)) {
|
|
241
261
|
mkdirSync(rulesDir, { recursive: true });
|
|
@@ -243,49 +263,25 @@ async function createRulesSyncPR(adaptation, claudeMdContent, changesSummary) {
|
|
|
243
263
|
writeFileSync(rulesFile, adaptation.adaptedContent, 'utf-8');
|
|
244
264
|
console.log(` ā
${RULES_FILE}`);
|
|
245
265
|
// Write CLAUDE.md (stripped version)
|
|
246
|
-
const claudeFile = join(
|
|
266
|
+
const claudeFile = join(workspaceRootPath, CLAUDE_MD_FILE);
|
|
247
267
|
writeFileSync(claudeFile, claudeMdContent, 'utf-8');
|
|
248
268
|
console.log(` ā
${CLAUDE_MD_FILE}`);
|
|
249
|
-
// Add files to git
|
|
250
|
-
await git.add([RULES_FILE, CLAUDE_MD_FILE]);
|
|
251
269
|
// Run formatting and linting
|
|
252
270
|
console.log('\nš§ Running formatting and linting...');
|
|
253
271
|
await runFormat();
|
|
254
272
|
console.log(' ā
Formatting completed');
|
|
255
273
|
await runLint();
|
|
256
274
|
console.log(' ā
Linting completed');
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
await git.push('origin', branchName, ['--set-upstream']);
|
|
263
|
-
// Create PR
|
|
264
|
-
console.log('š Creating pull request...');
|
|
265
|
-
const date = new Date().toISOString().split('T')[0];
|
|
266
|
-
// Build PR body with LLM-generated summary
|
|
267
|
-
const prBody = `## š Sync Rules from Kosuke Template
|
|
268
|
-
|
|
269
|
-
${changesSummary}
|
|
270
|
-
|
|
271
|
-
---
|
|
272
|
-
|
|
273
|
-
š¤ *Auto-generated by \`bun run kosuke sync-rules\`*
|
|
274
|
-
`;
|
|
275
|
-
const prUrl = await createPullRequest({
|
|
276
|
-
owner,
|
|
277
|
-
repo,
|
|
278
|
-
title: `chore: sync rules & docs from kosuke-template (${date})`,
|
|
279
|
-
head: branchName,
|
|
280
|
-
base: TARGET_BRANCH,
|
|
281
|
-
body: prBody,
|
|
282
|
-
});
|
|
283
|
-
console.log(`ā
Pull request created: ${prUrl}`);
|
|
275
|
+
return {
|
|
276
|
+
adaptation,
|
|
277
|
+
claudeMdContent,
|
|
278
|
+
changesSummary,
|
|
279
|
+
};
|
|
284
280
|
}
|
|
285
281
|
/**
|
|
286
282
|
* Main sync-rules command
|
|
287
283
|
*/
|
|
288
|
-
export async function syncRulesCommand(
|
|
284
|
+
export async function syncRulesCommand(options = {}) {
|
|
289
285
|
console.log('š Starting Rules & Documentation Sync...\n');
|
|
290
286
|
try {
|
|
291
287
|
// Check if running in kosuke-template itself
|
|
@@ -299,55 +295,63 @@ export async function syncRulesCommand(force = false) {
|
|
|
299
295
|
if (!process.env.ANTHROPIC_API_KEY) {
|
|
300
296
|
throw new Error('ANTHROPIC_API_KEY environment variable is required');
|
|
301
297
|
}
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
298
|
+
// If --pr flag is provided, wrap with PR workflow
|
|
299
|
+
if (options.pr) {
|
|
300
|
+
if (!process.env.GITHUB_TOKEN) {
|
|
301
|
+
throw new Error('GITHUB_TOKEN environment variable is required for --pr flag');
|
|
302
|
+
}
|
|
303
|
+
const date = new Date().toISOString().split('T')[0];
|
|
304
|
+
try {
|
|
305
|
+
const { result, prInfo } = await runWithPR({
|
|
306
|
+
branchPrefix: 'sync/rules',
|
|
307
|
+
baseBranch: options.baseBranch,
|
|
308
|
+
commitMessage: 'chore: sync rules and documentation from kosuke-template',
|
|
309
|
+
prTitle: `chore: sync rules & docs from kosuke-template (${date})`,
|
|
310
|
+
prBody: `## š Sync Rules from Kosuke Template
|
|
311
|
+
|
|
312
|
+
This PR syncs rules and documentation from the kosuke-template repository.
|
|
313
|
+
|
|
314
|
+
### š Changes
|
|
315
|
+
- Updated \`.cursor/rules/general.mdc\`
|
|
316
|
+
- Updated \`CLAUDE.md\`
|
|
317
|
+
|
|
318
|
+
---
|
|
319
|
+
|
|
320
|
+
š¤ *Auto-generated by \`kosuke sync-rules --pr\`*`,
|
|
321
|
+
}, async () => syncRulesCore(options.force || false));
|
|
322
|
+
console.log('\nā
Rules sync completed successfully!');
|
|
323
|
+
console.log(`š Changes summary: ${result.changesSummary}`);
|
|
324
|
+
console.log(`š PR: ${prInfo.prUrl}`);
|
|
325
|
+
}
|
|
326
|
+
catch (error) {
|
|
327
|
+
if (error instanceof Error &&
|
|
328
|
+
(error.message === 'No recent changes' ||
|
|
329
|
+
error.message === 'No differences detected' ||
|
|
330
|
+
error.message === 'No relevant changes')) {
|
|
331
|
+
console.log('\nā
No sync needed.');
|
|
332
|
+
return;
|
|
333
|
+
}
|
|
334
|
+
throw error;
|
|
335
|
+
}
|
|
309
336
|
}
|
|
310
337
|
else {
|
|
311
|
-
//
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
console.log('
|
|
316
|
-
|
|
317
|
-
|
|
338
|
+
// Run core logic without PR
|
|
339
|
+
try {
|
|
340
|
+
await syncRulesCore(options.force || false);
|
|
341
|
+
console.log('\nā
Rules sync completed successfully!');
|
|
342
|
+
console.log('\nā¹ļø Changes applied locally. Use --pr flag to create a pull request.');
|
|
343
|
+
}
|
|
344
|
+
catch (error) {
|
|
345
|
+
if (error instanceof Error &&
|
|
346
|
+
(error.message === 'No recent changes' ||
|
|
347
|
+
error.message === 'No differences detected' ||
|
|
348
|
+
error.message === 'No relevant changes')) {
|
|
349
|
+
console.log('\nā
No sync needed.');
|
|
350
|
+
return;
|
|
351
|
+
}
|
|
352
|
+
throw error;
|
|
318
353
|
}
|
|
319
|
-
console.log(` ā
Found changes in ${RULES_FILE}\n`);
|
|
320
|
-
}
|
|
321
|
-
// Read current repository versions
|
|
322
|
-
const workspaceRoot = process.cwd();
|
|
323
|
-
const kosukeFile = join(TEMP_DIR, RULES_FILE);
|
|
324
|
-
const currentFile = join(workspaceRoot, RULES_FILE);
|
|
325
|
-
if (!existsSync(kosukeFile)) {
|
|
326
|
-
throw new Error(`${RULES_FILE} not found in kosuke-template`);
|
|
327
|
-
}
|
|
328
|
-
const kosukeContent = readFileSync(kosukeFile, 'utf-8');
|
|
329
|
-
const currentContent = existsSync(currentFile) ? readFileSync(currentFile, 'utf-8') : '';
|
|
330
|
-
// Check if content is actually different
|
|
331
|
-
if (kosukeContent === currentContent) {
|
|
332
|
-
console.log(`ā¹ļø No differences detected in ${RULES_FILE}. Nothing to sync.`);
|
|
333
|
-
return;
|
|
334
|
-
}
|
|
335
|
-
console.log(`š„ Processing ${RULES_FILE}...`);
|
|
336
|
-
const adaptation = await adaptRulesWithClaude(RULES_FILE, currentContent);
|
|
337
|
-
// Abort if no changes
|
|
338
|
-
if (!adaptation.relevant) {
|
|
339
|
-
console.log('ā
No relevant changes to sync. Aborting.');
|
|
340
|
-
return;
|
|
341
354
|
}
|
|
342
|
-
// Generate CLAUDE.md from adapted general.mdc
|
|
343
|
-
console.log(`\nš Generating ${CLAUDE_MD_FILE} from ${RULES_FILE}...`);
|
|
344
|
-
const claudeMdContent = generateClaudeMd(adaptation.adaptedContent);
|
|
345
|
-
// Generate LLM summary of changes
|
|
346
|
-
const changesSummary = await generateChangesSummary(currentContent, adaptation.adaptedContent);
|
|
347
|
-
// Create PR with adapted content
|
|
348
|
-
console.log(`\nš Creating pull request...\n`);
|
|
349
|
-
await createRulesSyncPR(adaptation, claudeMdContent, changesSummary);
|
|
350
|
-
console.log('\nā
Rules sync completed successfully!');
|
|
351
355
|
}
|
|
352
356
|
catch (error) {
|
|
353
357
|
console.error('\nā Sync failed:', error);
|