@xortex/xcode 3.0.8 → 3.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/INSTALLATION.md +285 -0
- package/QUICKSTART.md +151 -0
- package/SYSTEM_PROMPT.md +583 -0
- package/SYSTEM_PROMPT_EXTRACTED.md +1 -0
- package/Untitled +1 -0
- package/bin/xcode +33 -85
- package/bootstrap/state.ts +1758 -0
- package/bun.lock +645 -0
- package/context/QueuedMessageContext.tsx +63 -0
- package/context/fpsMetrics.tsx +30 -0
- package/context/mailbox.tsx +38 -0
- package/context/modalContext.tsx +58 -0
- package/context/notifications.tsx +240 -0
- package/context/overlayContext.tsx +151 -0
- package/context/promptOverlayContext.tsx +125 -0
- package/context/stats.tsx +220 -0
- package/context/voice.tsx +88 -0
- package/coordinator/coordinatorMode.ts +369 -0
- package/costHook.ts +22 -0
- package/dialogLaunchers.tsx +133 -0
- package/entrypoints/cli.tsx +1 -1
- package/extract_prompt.ts +304 -0
- package/ink.ts +85 -0
- package/install.sh +221 -0
- package/interactiveHelpers.tsx +366 -0
- package/macro.ts +1 -1
- package/memdir/findRelevantMemories.ts +141 -0
- package/memdir/memdir.ts +511 -0
- package/memdir/memoryAge.ts +53 -0
- package/memdir/memoryScan.ts +94 -0
- package/memdir/memoryTypes.ts +271 -0
- package/memdir/paths.ts +291 -0
- package/memdir/teamMemPaths.ts +292 -0
- package/memdir/teamMemPrompts.ts +100 -0
- package/moreright/useMoreRight.tsx +26 -0
- package/native-ts/color-diff/index.ts +999 -0
- package/native-ts/file-index/index.ts +370 -0
- package/native-ts/yoga-layout/enums.ts +134 -0
- package/native-ts/yoga-layout/index.ts +2578 -0
- package/outputStyles/loadOutputStylesDir.ts +98 -0
- package/package.json +3 -42
- package/plugins/builtinPlugins.ts +159 -0
- package/plugins/bundled/index.ts +23 -0
- package/projectOnboardingState.ts +83 -0
- package/public/claude-files.png +0 -0
- package/public/leak-tweet.png +0 -0
- package/query/config.ts +46 -0
- package/query/deps.ts +40 -0
- package/query/stopHooks.ts +470 -0
- package/query/tokenBudget.ts +93 -0
- package/replLauncher.tsx +27 -0
- package/schemas/hooks.ts +222 -0
- package/screens/Doctor.tsx +575 -0
- package/screens/REPL.tsx +7107 -0
- package/screens/ResumeConversation.tsx +399 -0
- package/scripts/postinstall.js +90 -0
- package/server/createDirectConnectSession.ts +88 -0
- package/server/directConnectManager.ts +213 -0
- package/server/types.ts +57 -0
- package/setup.ts +477 -0
- package/stub_types.sh +13 -0
- package/tasks.ts +39 -0
- package/tools.ts +396 -0
- package/upstreamproxy/relay.ts +455 -0
- package/upstreamproxy/upstreamproxy.ts +285 -0
- package/vim/motions.ts +82 -0
- package/vim/operators.ts +556 -0
- package/vim/textObjects.ts +186 -0
- package/vim/transitions.ts +490 -0
- package/vim/types.ts +199 -0
- package/voice/voiceModeEnabled.ts +54 -0
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* extract_prompt.ts
|
|
3
|
+
* Extracts and prints the real Claude Code system prompt by directly
|
|
4
|
+
* reading and evaluating all prompt-generating functions from source.
|
|
5
|
+
* Run with: bun extract_prompt.ts
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// ── Mock bun:bundle feature() macro (always returns false for clean external build) ──
|
|
9
|
+
// We patch this before any module loads it
|
|
10
|
+
const Module = require('module')
|
|
11
|
+
const originalLoad = Module._load
|
|
12
|
+
Module._load = function (request: string, ...args: unknown[]) {
|
|
13
|
+
if (request === 'bun:bundle') {
|
|
14
|
+
return { feature: (_: string) => false }
|
|
15
|
+
}
|
|
16
|
+
return originalLoad.call(this, request, ...args)
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// ── Read raw source file and extract string content from template literals ──
|
|
20
|
+
import { readFileSync } from 'fs'
|
|
21
|
+
import { join } from 'path'
|
|
22
|
+
|
|
23
|
+
const ROOT = import.meta.dir
|
|
24
|
+
|
|
25
|
+
function readSource(rel: string): string {
|
|
26
|
+
return readFileSync(join(ROOT, rel), 'utf-8')
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// Extract all backtick template literal bodies from a function by name
|
|
30
|
+
function extractTemplateLiterals(src: string): string[] {
|
|
31
|
+
const results: string[] = []
|
|
32
|
+
let i = 0
|
|
33
|
+
while (i < src.length) {
|
|
34
|
+
if (src[i] === '`') {
|
|
35
|
+
let j = i + 1
|
|
36
|
+
let body = ''
|
|
37
|
+
while (j < src.length) {
|
|
38
|
+
if (src[j] === '\\') { body += src[j] + src[j+1]; j += 2; continue }
|
|
39
|
+
if (src[j] === '`') break
|
|
40
|
+
body += src[j]
|
|
41
|
+
j++
|
|
42
|
+
}
|
|
43
|
+
results.push(body)
|
|
44
|
+
i = j + 1
|
|
45
|
+
} else {
|
|
46
|
+
i++
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return results
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// ── Extract sections from prompts.ts ────────────────────────────────────────
|
|
53
|
+
|
|
54
|
+
const promptsSrc = readSource('constants/prompts.ts')
|
|
55
|
+
const systemSrc = readSource('constants/system.ts')
|
|
56
|
+
const coordSrc = readSource('coordinator/coordinatorMode.ts')
|
|
57
|
+
const cyberSrc = readSource('constants/cyberRiskInstruction.ts')
|
|
58
|
+
|
|
59
|
+
// Pull CYBER_RISK_INSTRUCTION
|
|
60
|
+
const cyberMatch = cyberSrc.match(/CYBER_RISK_INSTRUCTION\s*=\s*`([^`]+)`/)
|
|
61
|
+
const CYBER_RISK = cyberMatch?.[1] ?? '[cyber risk instruction not found]'
|
|
62
|
+
|
|
63
|
+
// Pull coordinator system prompt (between the return template literal)
|
|
64
|
+
const coordMatch = coordSrc.match(/return\s*`(You are Claude Code, an AI assistant[\s\S]+?)`\s*\}/)
|
|
65
|
+
const COORDINATOR_PROMPT = coordMatch?.[1] ?? '[coordinator prompt not found]'
|
|
66
|
+
|
|
67
|
+
// Helper: extract named function body
|
|
68
|
+
function getFunctionBody(src: string, fnName: string): string {
|
|
69
|
+
const idx = src.indexOf(`function ${fnName}(`)
|
|
70
|
+
if (idx === -1) return `[${fnName} not found]`
|
|
71
|
+
let depth = 0
|
|
72
|
+
let start = -1
|
|
73
|
+
for (let i = idx; i < src.length; i++) {
|
|
74
|
+
if (src[i] === '{') { if (start === -1) start = i; depth++ }
|
|
75
|
+
else if (src[i] === '}') { depth--; if (depth === 0) return src.slice(start, i+1) }
|
|
76
|
+
}
|
|
77
|
+
return `[${fnName} body unterminated]`
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
// Extract all return template strings from a function
|
|
81
|
+
function getReturnStrings(fnBody: string): string[] {
|
|
82
|
+
// Find return `...` blocks
|
|
83
|
+
const results: string[] = []
|
|
84
|
+
const matches = fnBody.matchAll(/return\s*`([\s\S]*?)`/g)
|
|
85
|
+
for (const m of matches) results.push(m[1])
|
|
86
|
+
return results
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// ── Manually inline relevant prompt section text ─────────────────────────────
|
|
90
|
+
|
|
91
|
+
// 1. getSimpleIntroSection
|
|
92
|
+
const introFn = getFunctionBody(promptsSrc, 'getSimpleIntroSection')
|
|
93
|
+
const introStr = getReturnStrings(introFn)
|
|
94
|
+
|
|
95
|
+
// 2. getSimpleSystemSection
|
|
96
|
+
const sysFn = getFunctionBody(promptsSrc, 'getSimpleSystemSection')
|
|
97
|
+
|
|
98
|
+
// 3. getSimpleDoingTasksSection
|
|
99
|
+
const doingFn = getFunctionBody(promptsSrc, 'getSimpleDoingTasksSection')
|
|
100
|
+
|
|
101
|
+
// 4. getActionsSection
|
|
102
|
+
const actionsFn = getFunctionBody(promptsSrc, 'getActionsSection')
|
|
103
|
+
const actionsStr = getReturnStrings(actionsFn)
|
|
104
|
+
|
|
105
|
+
// 5. getOutputEfficiencySection
|
|
106
|
+
const effFn = getFunctionBody(promptsSrc, 'getOutputEfficiencySection')
|
|
107
|
+
const effStrings = getReturnStrings(effFn)
|
|
108
|
+
|
|
109
|
+
// 6. computeSimpleEnvInfo - template
|
|
110
|
+
const envFn = getFunctionBody(promptsSrc, 'computeSimpleEnvInfo')
|
|
111
|
+
const envTemplate = getReturnStrings(envFn)
|
|
112
|
+
|
|
113
|
+
// 7. getScratchpadInstructions
|
|
114
|
+
const scratchFn = getFunctionBody(promptsSrc, 'getScratchpadInstructions')
|
|
115
|
+
const scratchStr = getReturnStrings(scratchFn)
|
|
116
|
+
|
|
117
|
+
// 8. DEFAULT_AGENT_PROMPT
|
|
118
|
+
const agentMatch = promptsSrc.match(/DEFAULT_AGENT_PROMPT\s*=\s*`([^`]+)`/)
|
|
119
|
+
const DEFAULT_AGENT_PROMPT = agentMatch?.[1] ?? '[not found]'
|
|
120
|
+
|
|
121
|
+
// 9. SUMMARIZE_TOOL_RESULTS_SECTION
|
|
122
|
+
const sumMatch = promptsSrc.match(/SUMMARIZE_TOOL_RESULTS_SECTION\s*=\s*`([^`]+)`/)
|
|
123
|
+
const SUMMARIZE = sumMatch?.[1] ?? '[not found]'
|
|
124
|
+
|
|
125
|
+
// 10. getSystemRemindersSection
|
|
126
|
+
const remMatch = promptsSrc.match(/function getSystemRemindersSection[\s\S]*?return\s*`([\s\S]*?)`/)
|
|
127
|
+
const SYSTEM_REMINDERS = remMatch?.[1] ?? '[not found]'
|
|
128
|
+
|
|
129
|
+
// 11. getHooksSection
|
|
130
|
+
const hooksMatch = promptsSrc.match(/function getHooksSection[\s\S]*?return\s*`([\s\S]*?)`/)
|
|
131
|
+
const HOOKS = hooksMatch?.[1] ?? '[not found]'
|
|
132
|
+
|
|
133
|
+
// 12. getFunctionResultClearingSection template
|
|
134
|
+
const frcMatch = promptsSrc.match(/return\s*`# Function Result Clearing[\s\S]*?`/)
|
|
135
|
+
const FRC = frcMatch?.[0]?.replace(/^return\s*`/, '').replace(/`$/, '') ?? '[not found]'
|
|
136
|
+
|
|
137
|
+
// 13. Token budget section
|
|
138
|
+
const tokenMatch = promptsSrc.match(/'token_budget',\s*\(\)\s*=>\s*'([\s\S]*?)',/)
|
|
139
|
+
const TOKEN_BUDGET = tokenMatch?.[1] ?? '[not found]'
|
|
140
|
+
|
|
141
|
+
// 14. Proactive section
|
|
142
|
+
const proactiveFn = getFunctionBody(promptsSrc, 'getProactiveSection')
|
|
143
|
+
const proactiveStr = getReturnStrings(proactiveFn)
|
|
144
|
+
|
|
145
|
+
// 15. getSimpleToneAndStyleSection items
|
|
146
|
+
const toneFn = getFunctionBody(promptsSrc, 'getSimpleToneAndStyleSection')
|
|
147
|
+
|
|
148
|
+
// 16. getMcpInstructions template
|
|
149
|
+
const mcpMatch = promptsSrc.match(/return\s*`# MCP Server Instructions[\s\S]*?`/)
|
|
150
|
+
const MCP_TEMPLATE = mcpMatch?.[0]?.replace(/^return\s*`/, '').replace(/`$/, '') ?? '[not found]'
|
|
151
|
+
|
|
152
|
+
// ── Build and print the full prompt ──────────────────────────────────────────
|
|
153
|
+
|
|
154
|
+
const HR = '\n' + '='.repeat(80) + '\n'
|
|
155
|
+
const output: string[] = []
|
|
156
|
+
|
|
157
|
+
output.push(`# CLAUDE CODE — REAL SYSTEM PROMPT (Extracted from Source)`)
|
|
158
|
+
output.push(`Generated by extract_prompt.ts — reads directly from constants/prompts.ts\n`)
|
|
159
|
+
|
|
160
|
+
output.push(HR)
|
|
161
|
+
output.push(`## SECTION 0 — IDENTITY PREFIX`)
|
|
162
|
+
output.push(`\`\`\``)
|
|
163
|
+
output.push(`You are Claude Code, Anthropic's official CLI for Claude.`)
|
|
164
|
+
output.push(`\`\`\``)
|
|
165
|
+
|
|
166
|
+
output.push(HR)
|
|
167
|
+
output.push(`## SECTION 1 — SIMPLE MODE (env CLAUDE_CODE_SIMPLE=1)`)
|
|
168
|
+
output.push(`\`\`\``)
|
|
169
|
+
output.push(`You are Claude Code, Anthropic's official CLI for Claude.\n\nCWD: <cwd>\nDate: <session start date>`)
|
|
170
|
+
output.push(`\`\`\``)
|
|
171
|
+
|
|
172
|
+
output.push(HR)
|
|
173
|
+
output.push(`## SECTION 2 — INTRO (getSimpleIntroSection)`)
|
|
174
|
+
output.push(`\`\`\``)
|
|
175
|
+
output.push(`\nYou are an interactive agent that helps users with software engineering tasks. Use the instructions below and the tools available to you to assist the user.\n\n${CYBER_RISK}\nIMPORTANT: You must NEVER generate or guess URLs for the user unless you are confident that the URLs are for helping the user with programming. You may use URLs provided by the user in their messages or local files.`)
|
|
176
|
+
output.push(`\`\`\``)
|
|
177
|
+
|
|
178
|
+
output.push(HR)
|
|
179
|
+
output.push(`## SECTION 3 — SYSTEM (getSimpleSystemSection)`)
|
|
180
|
+
// Extract bullet items from the array literal in getSimpleSystemSection
|
|
181
|
+
const systemItemsMatch = promptsSrc.match(/function getSimpleSystemSection[\s\S]*?const items = \[([\s\S]*?)\]/m)
|
|
182
|
+
if (systemItemsMatch) {
|
|
183
|
+
// Pull backtick strings out of the items array
|
|
184
|
+
const itemsBlock = systemItemsMatch[1]
|
|
185
|
+
const ticks = extractTemplateLiterals(itemsBlock)
|
|
186
|
+
|
|
187
|
+
// Replace HOOKS placeholder
|
|
188
|
+
const finalItems = ticks.map(t => t.replace(/\${getHooksSection\(\)}/, HOOKS))
|
|
189
|
+
|
|
190
|
+
output.push(`\`\`\``)
|
|
191
|
+
output.push(`# System`)
|
|
192
|
+
finalItems.forEach(item => output.push(` - ${item}`))
|
|
193
|
+
output.push(`\`\`\``)
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
output.push(HR)
|
|
197
|
+
output.push(`## SECTION 4 — ACTIONS (getActionsSection)`)
|
|
198
|
+
output.push(`\`\`\``)
|
|
199
|
+
if (actionsStr[0]) output.push(actionsStr[0].replace(/\\n/g, '\n'))
|
|
200
|
+
output.push(`\`\`\``)
|
|
201
|
+
|
|
202
|
+
output.push(HR)
|
|
203
|
+
output.push(`## SECTION 5 — DOING TASKS (getSimpleDoingTasksSection) — key items`)
|
|
204
|
+
// Extract the outer items array
|
|
205
|
+
const doingItemsRegex = /`The user will primarily[\s\S]*?`/g
|
|
206
|
+
const doingMatches = [...doingFn.matchAll(/`([^`]{20,})`/g)].map(m => m[1]).filter(s => !s.includes('${'))
|
|
207
|
+
output.push(`\`\`\``)
|
|
208
|
+
output.push(`# Doing tasks`)
|
|
209
|
+
doingMatches.slice(0, 15).forEach(i => output.push(` - ${i}`))
|
|
210
|
+
output.push(`\`\`\``)
|
|
211
|
+
|
|
212
|
+
output.push(HR)
|
|
213
|
+
output.push(`## SECTION 6 — TONE AND STYLE (getSimpleToneAndStyleSection)`)
|
|
214
|
+
const toneItems = [...toneFn.matchAll(/`([^`]{20,})`/g)].map(m => m[1]).filter(s => !s.includes('${'))
|
|
215
|
+
output.push(`\`\`\``)
|
|
216
|
+
output.push(`# Tone and style`)
|
|
217
|
+
toneItems.forEach(i => output.push(` - ${i}`))
|
|
218
|
+
output.push(`\`\`\``)
|
|
219
|
+
|
|
220
|
+
output.push(HR)
|
|
221
|
+
output.push(`## SECTION 7 — OUTPUT EFFICIENCY (getOutputEfficiencySection)`)
|
|
222
|
+
output.push(`\`\`\``)
|
|
223
|
+
if (effStrings[1]) output.push(effStrings[1])
|
|
224
|
+
else if (effStrings[0]) output.push(effStrings[0])
|
|
225
|
+
output.push(`\`\`\``)
|
|
226
|
+
|
|
227
|
+
output.push(HR)
|
|
228
|
+
output.push(`## SECTION 8 — ENVIRONMENT (computeSimpleEnvInfo) — template`)
|
|
229
|
+
output.push(`\`\`\``)
|
|
230
|
+
output.push(`# Environment
|
|
231
|
+
You have been invoked in the following environment:
|
|
232
|
+
- Primary working directory: <cwd>
|
|
233
|
+
- Is a git repository: Yes/No
|
|
234
|
+
- Platform: darwin/linux/win32
|
|
235
|
+
- Shell: zsh/bash
|
|
236
|
+
- OS Version: Darwin 25.x.x
|
|
237
|
+
- You are powered by the model named <model>. The exact model ID is <model-id>.
|
|
238
|
+
- Assistant knowledge cutoff is <date>.
|
|
239
|
+
- The most recent Claude model family is Claude 4.5/4.6. Model IDs — Opus 4.6: 'claude-opus-4-6', Sonnet 4.6: 'claude-sonnet-4-6', Haiku 4.5: 'claude-haiku-4-5-20251001'. When building AI applications, default to the latest and most capable Claude models.
|
|
240
|
+
- Claude Code is available as a CLI in the terminal, desktop app (Mac/Windows), web app (claude.ai/code), and IDE extensions (VS Code, JetBrains).
|
|
241
|
+
- Fast mode for Claude Code uses the same Claude Opus 4.6 model with faster output. It does NOT switch to a different model. It can be toggled with /fast.`)
|
|
242
|
+
output.push(`\`\`\``)
|
|
243
|
+
|
|
244
|
+
output.push(HR)
|
|
245
|
+
output.push(`## SECTION 9 — SYSTEM REMINDERS (getSystemRemindersSection)`)
|
|
246
|
+
output.push(`\`\`\``)
|
|
247
|
+
output.push(SYSTEM_REMINDERS)
|
|
248
|
+
output.push(`\`\`\``)
|
|
249
|
+
|
|
250
|
+
output.push(HR)
|
|
251
|
+
output.push(`## SECTION 10 — SUMMARIZE TOOL RESULTS`)
|
|
252
|
+
output.push(`\`\`\``)
|
|
253
|
+
output.push(SUMMARIZE)
|
|
254
|
+
output.push(`\`\`\``)
|
|
255
|
+
|
|
256
|
+
output.push(HR)
|
|
257
|
+
output.push(`## SECTION 11 — SCRATCHPAD DIRECTORY (getScratchpadInstructions)`)
|
|
258
|
+
output.push(`\`\`\``)
|
|
259
|
+
if (scratchStr[0]) output.push(scratchStr[0])
|
|
260
|
+
output.push(`\`\`\``)
|
|
261
|
+
|
|
262
|
+
output.push(HR)
|
|
263
|
+
output.push(`## SECTION 12 — MCP SERVER INSTRUCTIONS TEMPLATE`)
|
|
264
|
+
output.push(`\`\`\``)
|
|
265
|
+
output.push(MCP_TEMPLATE)
|
|
266
|
+
output.push(`\`\`\``)
|
|
267
|
+
|
|
268
|
+
output.push(HR)
|
|
269
|
+
output.push(`## SECTION 13 — FUNCTION RESULT CLEARING`)
|
|
270
|
+
output.push(`\`\`\``)
|
|
271
|
+
output.push(FRC)
|
|
272
|
+
output.push(`\`\`\``)
|
|
273
|
+
|
|
274
|
+
output.push(HR)
|
|
275
|
+
output.push(`## SECTION 14 — TOKEN BUDGET`)
|
|
276
|
+
output.push(`\`\`\``)
|
|
277
|
+
output.push(TOKEN_BUDGET)
|
|
278
|
+
output.push(`\`\`\``)
|
|
279
|
+
|
|
280
|
+
output.push(HR)
|
|
281
|
+
output.push(`## SECTION 15 — DEFAULT AGENT PROMPT`)
|
|
282
|
+
output.push(`\`\`\``)
|
|
283
|
+
output.push(DEFAULT_AGENT_PROMPT)
|
|
284
|
+
output.push(`\`\`\``)
|
|
285
|
+
|
|
286
|
+
output.push(HR)
|
|
287
|
+
output.push(`## SECTION 16 — COORDINATOR MODE SYSTEM PROMPT`)
|
|
288
|
+
output.push(`\`\`\``)
|
|
289
|
+
output.push(COORDINATOR_PROMPT)
|
|
290
|
+
output.push(`\`\`\``)
|
|
291
|
+
|
|
292
|
+
output.push(HR)
|
|
293
|
+
output.push(`## SECTION 17 — AUTONOMOUS / PROACTIVE MODE SECTION`)
|
|
294
|
+
output.push(`\`\`\``)
|
|
295
|
+
if (proactiveStr[0]) output.push(proactiveStr[0])
|
|
296
|
+
output.push(`\`\`\``)
|
|
297
|
+
|
|
298
|
+
const finalOutput = output.join('\n')
|
|
299
|
+
console.log(finalOutput)
|
|
300
|
+
|
|
301
|
+
// Also write to file
|
|
302
|
+
import { writeFileSync } from 'fs'
|
|
303
|
+
writeFileSync(join(ROOT, 'SYSTEM_PROMPT_EXTRACTED.md'), finalOutput, 'utf-8')
|
|
304
|
+
console.error('\n\nWritten to SYSTEM_PROMPT_EXTRACTED.md')
|
package/ink.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import { createElement, type ReactNode } from 'react'
|
|
2
|
+
import { ThemeProvider } from './components/design-system/ThemeProvider.js'
|
|
3
|
+
import inkRender, {
|
|
4
|
+
type Instance,
|
|
5
|
+
createRoot as inkCreateRoot,
|
|
6
|
+
type RenderOptions,
|
|
7
|
+
type Root,
|
|
8
|
+
} from './ink/root.js'
|
|
9
|
+
|
|
10
|
+
export type { RenderOptions, Instance, Root }
|
|
11
|
+
|
|
12
|
+
// Wrap all CC render calls with ThemeProvider so ThemedBox/ThemedText work
|
|
13
|
+
// without every call site having to mount it. Ink itself is theme-agnostic.
|
|
14
|
+
function withTheme(node: ReactNode): ReactNode {
|
|
15
|
+
return createElement(ThemeProvider, null, node)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export async function render(
|
|
19
|
+
node: ReactNode,
|
|
20
|
+
options?: NodeJS.WriteStream | RenderOptions,
|
|
21
|
+
): Promise<Instance> {
|
|
22
|
+
return inkRender(withTheme(node), options)
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
export async function createRoot(options?: RenderOptions): Promise<Root> {
|
|
26
|
+
const root = await inkCreateRoot(options)
|
|
27
|
+
return {
|
|
28
|
+
...root,
|
|
29
|
+
render: node => root.render(withTheme(node)),
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { color } from './components/design-system/color.js'
|
|
34
|
+
export type { Props as BoxProps } from './components/design-system/ThemedBox.js'
|
|
35
|
+
export { default as Box } from './components/design-system/ThemedBox.js'
|
|
36
|
+
export type { Props as TextProps } from './components/design-system/ThemedText.js'
|
|
37
|
+
export { default as Text } from './components/design-system/ThemedText.js'
|
|
38
|
+
export {
|
|
39
|
+
ThemeProvider,
|
|
40
|
+
usePreviewTheme,
|
|
41
|
+
useTheme,
|
|
42
|
+
useThemeSetting,
|
|
43
|
+
} from './components/design-system/ThemeProvider.js'
|
|
44
|
+
export { Ansi } from './ink/Ansi.js'
|
|
45
|
+
export type { Props as AppProps } from './ink/components/AppContext.js'
|
|
46
|
+
export type { Props as BaseBoxProps } from './ink/components/Box.js'
|
|
47
|
+
export { default as BaseBox } from './ink/components/Box.js'
|
|
48
|
+
export type {
|
|
49
|
+
ButtonState,
|
|
50
|
+
Props as ButtonProps,
|
|
51
|
+
} from './ink/components/Button.js'
|
|
52
|
+
export { default as Button } from './ink/components/Button.js'
|
|
53
|
+
export type { Props as LinkProps } from './ink/components/Link.js'
|
|
54
|
+
export { default as Link } from './ink/components/Link.js'
|
|
55
|
+
export type { Props as NewlineProps } from './ink/components/Newline.js'
|
|
56
|
+
export { default as Newline } from './ink/components/Newline.js'
|
|
57
|
+
export { NoSelect } from './ink/components/NoSelect.js'
|
|
58
|
+
export { RawAnsi } from './ink/components/RawAnsi.js'
|
|
59
|
+
export { default as Spacer } from './ink/components/Spacer.js'
|
|
60
|
+
export type { Props as StdinProps } from './ink/components/StdinContext.js'
|
|
61
|
+
export type { Props as BaseTextProps } from './ink/components/Text.js'
|
|
62
|
+
export { default as BaseText } from './ink/components/Text.js'
|
|
63
|
+
export type { DOMElement } from './ink/dom.js'
|
|
64
|
+
export { ClickEvent } from './ink/events/click-event.js'
|
|
65
|
+
export { EventEmitter } from './ink/events/emitter.js'
|
|
66
|
+
export { Event } from './ink/events/event.js'
|
|
67
|
+
export type { Key } from './ink/events/input-event.js'
|
|
68
|
+
export { InputEvent } from './ink/events/input-event.js'
|
|
69
|
+
export type { TerminalFocusEventType } from './ink/events/terminal-focus-event.js'
|
|
70
|
+
export { TerminalFocusEvent } from './ink/events/terminal-focus-event.js'
|
|
71
|
+
export { FocusManager } from './ink/focus.js'
|
|
72
|
+
export type { FlickerReason } from './ink/frame.js'
|
|
73
|
+
export { useAnimationFrame } from './ink/hooks/use-animation-frame.js'
|
|
74
|
+
export { default as useApp } from './ink/hooks/use-app.js'
|
|
75
|
+
export { default as useInput } from './ink/hooks/use-input.js'
|
|
76
|
+
export { useAnimationTimer, useInterval } from './ink/hooks/use-interval.js'
|
|
77
|
+
export { useSelection } from './ink/hooks/use-selection.js'
|
|
78
|
+
export { default as useStdin } from './ink/hooks/use-stdin.js'
|
|
79
|
+
export { useTabStatus } from './ink/hooks/use-tab-status.js'
|
|
80
|
+
export { useTerminalFocus } from './ink/hooks/use-terminal-focus.js'
|
|
81
|
+
export { useTerminalTitle } from './ink/hooks/use-terminal-title.js'
|
|
82
|
+
export { useTerminalViewport } from './ink/hooks/use-terminal-viewport.js'
|
|
83
|
+
export { default as measureElement } from './ink/measure-element.js'
|
|
84
|
+
export { supportsTabStatus } from './ink/termio/osc.js'
|
|
85
|
+
export { default as wrapText } from './ink/wrap-text.js'
|
package/install.sh
ADDED
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
#
|
|
3
|
+
# XCode Installation Script
|
|
4
|
+
#
|
|
5
|
+
# Install with:
|
|
6
|
+
# curl -fsSL https://raw.githubusercontent.com/XortexAI/XCode/main/install.sh | bash
|
|
7
|
+
#
|
|
8
|
+
# Or with wget:
|
|
9
|
+
# wget -qO- https://raw.githubusercontent.com/XortexAI/XCode/main/install.sh | bash
|
|
10
|
+
#
|
|
11
|
+
|
|
12
|
+
set -e
|
|
13
|
+
|
|
14
|
+
# Colors for output
|
|
15
|
+
RED='\033[0;31m'
|
|
16
|
+
GREEN='\033[0;32m'
|
|
17
|
+
YELLOW='\033[1;33m'
|
|
18
|
+
BLUE='\033[0;34m'
|
|
19
|
+
NC='\033[0m' # No Color
|
|
20
|
+
|
|
21
|
+
# Configuration
|
|
22
|
+
REPO_URL="https://github.com/XortexAI/XCode"
|
|
23
|
+
INSTALL_DIR="$HOME/.xcode"
|
|
24
|
+
BIN_DIR="$HOME/.local/bin"
|
|
25
|
+
|
|
26
|
+
# Detect OS and architecture
|
|
27
|
+
OS=$(uname -s)
|
|
28
|
+
ARCH=$(uname -m)
|
|
29
|
+
|
|
30
|
+
echo -e "${BLUE}🚀 Installing XCode...${NC}"
|
|
31
|
+
echo ""
|
|
32
|
+
|
|
33
|
+
# Check if required dependencies are installed
|
|
34
|
+
check_dependencies() {
|
|
35
|
+
local missing_deps=()
|
|
36
|
+
|
|
37
|
+
# Check for git
|
|
38
|
+
if ! command -v git &> /dev/null; then
|
|
39
|
+
missing_deps+=("git")
|
|
40
|
+
fi
|
|
41
|
+
|
|
42
|
+
# Check for either Bun or Node.js
|
|
43
|
+
if ! command -v bun &> /dev/null && ! command -v node &> /dev/null; then
|
|
44
|
+
missing_deps+=("bun or node")
|
|
45
|
+
fi
|
|
46
|
+
|
|
47
|
+
if [ ${#missing_deps[@]} -ne 0 ]; then
|
|
48
|
+
echo -e "${RED}❌ Missing required dependencies:${NC}"
|
|
49
|
+
for dep in "${missing_deps[@]}"; do
|
|
50
|
+
echo " - $dep"
|
|
51
|
+
done
|
|
52
|
+
echo ""
|
|
53
|
+
echo "Please install the missing dependencies and try again."
|
|
54
|
+
echo ""
|
|
55
|
+
echo "To install Bun (recommended):"
|
|
56
|
+
echo " curl -fsSL https://bun.sh/install | bash"
|
|
57
|
+
echo ""
|
|
58
|
+
echo "To install Node.js:"
|
|
59
|
+
echo " Visit https://nodejs.org/ or use your package manager"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# Create necessary directories
|
|
65
|
+
setup_directories() {
|
|
66
|
+
echo -e "${BLUE}📁 Creating directories...${NC}"
|
|
67
|
+
mkdir -p "$INSTALL_DIR"
|
|
68
|
+
mkdir -p "$BIN_DIR"
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
# Clone or update the repository
|
|
72
|
+
install_xcode() {
|
|
73
|
+
if [ -d "$INSTALL_DIR/.git" ]; then
|
|
74
|
+
echo -e "${BLUE}🔄 Updating existing installation...${NC}"
|
|
75
|
+
cd "$INSTALL_DIR"
|
|
76
|
+
git pull origin main
|
|
77
|
+
else
|
|
78
|
+
echo -e "${BLUE}📦 Cloning XCode repository...${NC}"
|
|
79
|
+
rm -rf "$INSTALL_DIR"
|
|
80
|
+
git clone --depth=1 "$REPO_URL" "$INSTALL_DIR"
|
|
81
|
+
cd "$INSTALL_DIR"
|
|
82
|
+
fi
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
# Install dependencies
|
|
86
|
+
install_dependencies() {
|
|
87
|
+
echo -e "${BLUE}📥 Installing dependencies...${NC}"
|
|
88
|
+
|
|
89
|
+
if command -v bun &> /dev/null; then
|
|
90
|
+
echo "Using Bun..."
|
|
91
|
+
bun install
|
|
92
|
+
elif command -v npm &> /dev/null; then
|
|
93
|
+
echo "Using npm..."
|
|
94
|
+
npm install
|
|
95
|
+
fi
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
# Create the launcher script
|
|
99
|
+
create_launcher() {
|
|
100
|
+
echo -e "${BLUE}🎯 Creating launcher...${NC}"
|
|
101
|
+
|
|
102
|
+
cat > "$BIN_DIR/xcode" << 'EOF'
|
|
103
|
+
#!/bin/bash
|
|
104
|
+
# XCode Launcher
|
|
105
|
+
|
|
106
|
+
INSTALL_DIR="$HOME/.xcode"
|
|
107
|
+
|
|
108
|
+
# Check if installation exists
|
|
109
|
+
if [ ! -d "$INSTALL_DIR" ]; then
|
|
110
|
+
echo "❌ XCode not found. Please install first:"
|
|
111
|
+
echo " curl -fsSL https://raw.githubusercontent.com/XortexAI/XCode/main/install.sh | bash"
|
|
112
|
+
exit 1
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
cd "$INSTALL_DIR"
|
|
116
|
+
|
|
117
|
+
# Use Bun if available, otherwise fall back to npm/npx
|
|
118
|
+
if command -v bun &> /dev/null; then
|
|
119
|
+
exec bun run ./entrypoints/cli.tsx "$@"
|
|
120
|
+
elif command -v npx &> /dev/null; then
|
|
121
|
+
exec npx tsx ./entrypoints/cli.tsx "$@"
|
|
122
|
+
else
|
|
123
|
+
echo "❌ Neither Bun nor npx is available. Please install Bun:"
|
|
124
|
+
echo " curl -fsSL https://bun.sh/install | bash"
|
|
125
|
+
exit 1
|
|
126
|
+
fi
|
|
127
|
+
EOF
|
|
128
|
+
|
|
129
|
+
chmod +x "$BIN_DIR/xcode"
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
# Add to PATH if needed
|
|
133
|
+
update_path() {
|
|
134
|
+
local shell_rc=""
|
|
135
|
+
local current_shell=$(basename "$SHELL")
|
|
136
|
+
|
|
137
|
+
case "$current_shell" in
|
|
138
|
+
bash)
|
|
139
|
+
shell_rc="$HOME/.bashrc"
|
|
140
|
+
;;
|
|
141
|
+
zsh)
|
|
142
|
+
shell_rc="$HOME/.zshrc"
|
|
143
|
+
;;
|
|
144
|
+
fish)
|
|
145
|
+
shell_rc="$HOME/.config/fish/config.fish"
|
|
146
|
+
;;
|
|
147
|
+
*)
|
|
148
|
+
shell_rc="$HOME/.profile"
|
|
149
|
+
;;
|
|
150
|
+
esac
|
|
151
|
+
|
|
152
|
+
# Check if BIN_DIR is already in PATH
|
|
153
|
+
if [[ ":$PATH:" != *":$BIN_DIR:"* ]]; then
|
|
154
|
+
echo -e "${BLUE}🔧 Adding $BIN_DIR to PATH in $shell_rc${NC}"
|
|
155
|
+
echo "export PATH=\"$BIN_DIR:\$PATH\"" >> "$shell_rc"
|
|
156
|
+
echo ""
|
|
157
|
+
echo -e "${YELLOW}⚠️ Please run: source $shell_rc${NC}"
|
|
158
|
+
echo " Or restart your terminal to use the 'xcode' command"
|
|
159
|
+
fi
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
# Setup XMem configuration
|
|
163
|
+
setup_xmem() {
|
|
164
|
+
echo ""
|
|
165
|
+
echo -e "${BLUE}🧠 XMem Memory Configuration${NC}"
|
|
166
|
+
echo "XCode uses XMem for long-term memory storage."
|
|
167
|
+
echo ""
|
|
168
|
+
|
|
169
|
+
# Check if XMem is already configured
|
|
170
|
+
if [ -z "$XMEM_API_URL" ]; then
|
|
171
|
+
echo -e "${YELLOW}⚠️ XMEM_API_URL not set${NC}"
|
|
172
|
+
echo " Using default: http://localhost:8000"
|
|
173
|
+
echo " Set it with: export XMEM_API_URL=http://your-xmem-server:8000"
|
|
174
|
+
fi
|
|
175
|
+
|
|
176
|
+
echo ""
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
# Print success message
|
|
180
|
+
print_success() {
|
|
181
|
+
echo ""
|
|
182
|
+
echo -e "${GREEN}✅ XCode installed successfully!${NC}"
|
|
183
|
+
echo ""
|
|
184
|
+
echo -e "${BLUE}🎉 Usage:${NC}"
|
|
185
|
+
echo " xcode # Start interactive session"
|
|
186
|
+
echo " xcode --model gemini-2.5-pro # Use Gemini 2.5 Pro"
|
|
187
|
+
echo " xcode --model kimi-k2.5 # Use Kimi K2.5"
|
|
188
|
+
echo " xcode --model deepseek-v3.2 # Use DeepSeek V3.2"
|
|
189
|
+
echo ""
|
|
190
|
+
echo -e "${BLUE}🔑 API Keys (set these environment variables):${NC}"
|
|
191
|
+
echo " OPENROUTER_API_KEY # For Gemini, Kimi, DeepSeek via OpenRouter"
|
|
192
|
+
echo " ANTHROPIC_API_KEY # For Claude models"
|
|
193
|
+
echo " GEMINI_API_KEY # For Google Gemini directly"
|
|
194
|
+
echo " XMEM_API_URL # XMem server URL (default: http://localhost:8000)"
|
|
195
|
+
echo ""
|
|
196
|
+
echo -e "${BLUE}📚 Documentation:${NC}"
|
|
197
|
+
echo " https://github.com/XortexAI/XCode#readme"
|
|
198
|
+
echo ""
|
|
199
|
+
echo -e "${GREEN}Happy coding! 🚀${NC}"
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
# Main installation flow
|
|
203
|
+
main() {
|
|
204
|
+
echo -e "${BLUE}╔════════════════════════════════════╗${NC}"
|
|
205
|
+
echo -e "${BLUE}║ XCode Installer v3.0.0 ║${NC}"
|
|
206
|
+
echo -e "${BLUE}║ AI Coding with XMem Memory ║${NC}"
|
|
207
|
+
echo -e "${BLUE}╚════════════════════════════════════╝${NC}"
|
|
208
|
+
echo ""
|
|
209
|
+
|
|
210
|
+
check_dependencies
|
|
211
|
+
setup_directories
|
|
212
|
+
install_xcode
|
|
213
|
+
install_dependencies
|
|
214
|
+
create_launcher
|
|
215
|
+
update_path
|
|
216
|
+
setup_xmem
|
|
217
|
+
print_success
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
# Run main function
|
|
221
|
+
main "$@"
|