cyrus-ai 0.1.2 ā 0.1.4
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 +15 -0
- package/app.mjs +73 -36
- package/package.json +6 -5
package/README.md
ADDED
package/app.mjs
CHANGED
|
@@ -10,8 +10,28 @@ import { URL } from 'url'
|
|
|
10
10
|
import open from 'open'
|
|
11
11
|
import readline from 'readline'
|
|
12
12
|
|
|
13
|
-
//
|
|
14
|
-
|
|
13
|
+
// Parse command line arguments
|
|
14
|
+
const args = process.argv.slice(2)
|
|
15
|
+
const envFileArg = args.find(arg => arg.startsWith('--env-file='))
|
|
16
|
+
|
|
17
|
+
// Handle --version argument
|
|
18
|
+
if (args.includes('--version')) {
|
|
19
|
+
try {
|
|
20
|
+
const pkg = JSON.parse(readFileSync('./package.json', 'utf-8'))
|
|
21
|
+
console.log(pkg.version)
|
|
22
|
+
} catch {
|
|
23
|
+
console.log('0.1.3') // fallback version
|
|
24
|
+
}
|
|
25
|
+
process.exit(0)
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
// Load environment variables only if --env-file is specified
|
|
29
|
+
if (envFileArg) {
|
|
30
|
+
const envFile = envFileArg.split('=')[1]
|
|
31
|
+
dotenv.config({ path: envFile })
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
|
|
15
35
|
|
|
16
36
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
17
37
|
|
|
@@ -27,32 +47,32 @@ class EdgeApp {
|
|
|
27
47
|
|
|
28
48
|
/**
|
|
29
49
|
* Load edge configuration (credentials and repositories)
|
|
50
|
+
* Note: Strips promptTemplatePath from all repositories to ensure built-in template is used
|
|
30
51
|
*/
|
|
31
52
|
loadEdgeConfig() {
|
|
32
53
|
const edgeConfigPath = './.edge-config.json'
|
|
54
|
+
let config = { repositories: [] }
|
|
55
|
+
|
|
33
56
|
if (existsSync(edgeConfigPath)) {
|
|
34
57
|
try {
|
|
35
|
-
|
|
58
|
+
config = JSON.parse(readFileSync(edgeConfigPath, 'utf-8'))
|
|
36
59
|
} catch (e) {
|
|
37
60
|
console.error('Failed to load edge config:', e.message)
|
|
38
61
|
}
|
|
39
62
|
}
|
|
40
63
|
|
|
41
|
-
//
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
}
|
|
51
|
-
} catch (error) {
|
|
52
|
-
// No config file found
|
|
64
|
+
// Strip promptTemplatePath from all repositories to ensure built-in template is used
|
|
65
|
+
if (config.repositories) {
|
|
66
|
+
config.repositories = config.repositories.map(repo => {
|
|
67
|
+
const { promptTemplatePath, ...repoWithoutTemplate } = repo
|
|
68
|
+
if (promptTemplatePath) {
|
|
69
|
+
console.log(`Ignoring custom prompt template for repository: ${repo.name} (using built-in template)`)
|
|
70
|
+
}
|
|
71
|
+
return repoWithoutTemplate
|
|
72
|
+
})
|
|
53
73
|
}
|
|
54
74
|
|
|
55
|
-
return
|
|
75
|
+
return config
|
|
56
76
|
}
|
|
57
77
|
|
|
58
78
|
/**
|
|
@@ -85,9 +105,16 @@ class EdgeApp {
|
|
|
85
105
|
const baseBranch = await question('Base branch (default: main): ') || 'main'
|
|
86
106
|
const workspaceBaseDir = await question(`Workspace directory (default: ${repositoryPath}/workspaces): `) || `${repositoryPath}/workspaces`
|
|
87
107
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
108
|
+
// Note: Prompt template is now hardcoded - no longer configurable
|
|
109
|
+
|
|
110
|
+
// Ask for MCP configuration
|
|
111
|
+
console.log('\nš§ MCP (Model Context Protocol) Configuration')
|
|
112
|
+
console.log('MCP allows Claude to access external tools and data sources.')
|
|
113
|
+
console.log('Examples: filesystem access, database connections, API integrations')
|
|
114
|
+
console.log('See: https://docs.anthropic.com/en/docs/claude-code/mcp')
|
|
115
|
+
console.log('')
|
|
116
|
+
const mcpConfigInput = await question('MCP config file path (optional, e.g., ./mcp-config.json): ')
|
|
117
|
+
const mcpConfigPath = mcpConfigInput.trim() || undefined
|
|
91
118
|
|
|
92
119
|
// Ask for allowed tools configuration
|
|
93
120
|
console.log('\nš§ Tool Configuration')
|
|
@@ -116,8 +143,8 @@ class EdgeApp {
|
|
|
116
143
|
linearToken: linearCredentials.linearToken,
|
|
117
144
|
workspaceBaseDir: resolve(workspaceBaseDir),
|
|
118
145
|
isActive: true,
|
|
119
|
-
...(
|
|
120
|
-
...(
|
|
146
|
+
...(allowedTools && { allowedTools }),
|
|
147
|
+
...(mcpConfigPath && { mcpConfigPath: resolve(mcpConfigPath) })
|
|
121
148
|
}
|
|
122
149
|
|
|
123
150
|
return repository
|
|
@@ -256,15 +283,10 @@ class EdgeApp {
|
|
|
256
283
|
*/
|
|
257
284
|
async start() {
|
|
258
285
|
try {
|
|
259
|
-
//
|
|
260
|
-
const proxyUrl = process.env.PROXY_URL
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
console.log('\nPlease add the following to your .env.cyrus file:')
|
|
264
|
-
console.log('PROXY_URL=https://cyrus-proxy.ceedar.workers.dev')
|
|
265
|
-
console.log('\nThis connects to the secure public Cyrus proxy for Linear OAuth and webhooks.')
|
|
266
|
-
process.exit(1)
|
|
267
|
-
}
|
|
286
|
+
// Set proxy URL with default
|
|
287
|
+
const proxyUrl = process.env.PROXY_URL || 'https://cyrus-proxy.ceedar.workers.dev'
|
|
288
|
+
|
|
289
|
+
// No need to validate Claude CLI - using Claude TypeScript SDK now
|
|
268
290
|
|
|
269
291
|
// Start OAuth server immediately for easy access
|
|
270
292
|
const oauthPort = 3457
|
|
@@ -422,8 +444,7 @@ class EdgeApp {
|
|
|
422
444
|
const config = {
|
|
423
445
|
proxyUrl,
|
|
424
446
|
repositories,
|
|
425
|
-
|
|
426
|
-
allowedTools: process.env.ALLOWED_TOOLS?.split(',').map(t => t.trim()) || [],
|
|
447
|
+
defaultAllowedTools: process.env.ALLOWED_TOOLS?.split(',').map(t => t.trim()) || [],
|
|
427
448
|
features: {
|
|
428
449
|
enableContinuation: true
|
|
429
450
|
},
|
|
@@ -522,8 +543,12 @@ class EdgeApp {
|
|
|
522
543
|
throw new Error('Not a git repository')
|
|
523
544
|
}
|
|
524
545
|
|
|
546
|
+
// Sanitize branch name by removing backticks to prevent command injection
|
|
547
|
+
const sanitizeBranchName = (name) => name ? name.replace(/`/g, '') : name
|
|
548
|
+
|
|
525
549
|
// Use Linear's preferred branch name, or generate one if not available
|
|
526
|
-
const
|
|
550
|
+
const rawBranchName = issue.branchName || `${issue.identifier}-${issue.title?.toLowerCase().replace(/\s+/g, '-').substring(0, 30)}`
|
|
551
|
+
const branchName = sanitizeBranchName(rawBranchName)
|
|
527
552
|
const workspacePath = join(repository.workspaceBaseDir, issue.identifier)
|
|
528
553
|
|
|
529
554
|
// Ensure workspace directory exists
|
|
@@ -562,10 +587,22 @@ class EdgeApp {
|
|
|
562
587
|
// Branch doesn't exist, we'll create it
|
|
563
588
|
}
|
|
564
589
|
|
|
565
|
-
//
|
|
566
|
-
console.log(
|
|
590
|
+
// Fetch latest changes from remote
|
|
591
|
+
console.log('Fetching latest changes from remote...')
|
|
592
|
+
try {
|
|
593
|
+
execSync('git fetch origin', {
|
|
594
|
+
cwd: repository.repositoryPath,
|
|
595
|
+
stdio: 'pipe'
|
|
596
|
+
})
|
|
597
|
+
} catch (e) {
|
|
598
|
+
console.warn('Warning: git fetch failed, proceeding with local branch:', e.message)
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
// Create the worktree from remote branch
|
|
602
|
+
const remoteBranch = `origin/${repository.baseBranch}`
|
|
603
|
+
console.log(`Creating git worktree at ${workspacePath} from ${remoteBranch}`)
|
|
567
604
|
const worktreeCmd = createBranch
|
|
568
|
-
? `git worktree add "${workspacePath}" -b "${branchName}" "${
|
|
605
|
+
? `git worktree add "${workspacePath}" -b "${branchName}" "${remoteBranch}"`
|
|
569
606
|
: `git worktree add "${workspacePath}" "${branchName}"`
|
|
570
607
|
|
|
571
608
|
execSync(worktreeCmd, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cyrus-ai",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.4",
|
|
4
4
|
"description": "AI-powered Linear issue automation using Claude",
|
|
5
5
|
"main": "app.mjs",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"files": [
|
|
11
11
|
"app.mjs",
|
|
12
12
|
"services/**/*.mjs",
|
|
13
|
-
"utils/**/*.mjs"
|
|
13
|
+
"utils/**/*.mjs",
|
|
14
|
+
"README.md"
|
|
14
15
|
],
|
|
15
16
|
"publishConfig": {
|
|
16
17
|
"access": "public"
|
|
@@ -39,10 +40,9 @@
|
|
|
39
40
|
"open": "^10.0.0",
|
|
40
41
|
"zod": "^3.24.4",
|
|
41
42
|
"cyrus-core": "0.0.1",
|
|
42
|
-
"cyrus-
|
|
43
|
-
"cyrus-ndjson-client": "0.0.1",
|
|
43
|
+
"cyrus-edge-worker": "0.0.1",
|
|
44
44
|
"cyrus-claude-runner": "0.0.1",
|
|
45
|
-
"cyrus-
|
|
45
|
+
"cyrus-ndjson-client": "0.0.1"
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@vitest/ui": "^3.1.4",
|
|
@@ -53,6 +53,7 @@
|
|
|
53
53
|
"start": "node app.mjs",
|
|
54
54
|
"dev": "nodemon app.mjs",
|
|
55
55
|
"test": "vitest run",
|
|
56
|
+
"test:run": "vitest run --passWithNoTests",
|
|
56
57
|
"test:watch": "vitest"
|
|
57
58
|
}
|
|
58
59
|
}
|