@xortex/xcode 3.0.5 → 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.
Files changed (75) hide show
  1. package/INSTALLATION.md +285 -0
  2. package/QUICKSTART.md +151 -0
  3. package/SYSTEM_PROMPT.md +583 -0
  4. package/SYSTEM_PROMPT_EXTRACTED.md +1 -0
  5. package/Untitled +1 -0
  6. package/bin/xcode +69 -120
  7. package/bootstrap/state.ts +1758 -0
  8. package/bun-bundle-hook.js +38 -17
  9. package/bun-bundle-shim.ts +12 -0
  10. package/bun.lock +645 -0
  11. package/context/QueuedMessageContext.tsx +63 -0
  12. package/context/fpsMetrics.tsx +30 -0
  13. package/context/mailbox.tsx +38 -0
  14. package/context/modalContext.tsx +58 -0
  15. package/context/notifications.tsx +240 -0
  16. package/context/overlayContext.tsx +151 -0
  17. package/context/promptOverlayContext.tsx +125 -0
  18. package/context/stats.tsx +220 -0
  19. package/context/voice.tsx +88 -0
  20. package/coordinator/coordinatorMode.ts +369 -0
  21. package/costHook.ts +22 -0
  22. package/dialogLaunchers.tsx +133 -0
  23. package/entrypoints/cli.tsx +1 -1
  24. package/extract_prompt.ts +304 -0
  25. package/ink.ts +85 -0
  26. package/install.sh +221 -0
  27. package/interactiveHelpers.tsx +366 -0
  28. package/macro.ts +1 -1
  29. package/memdir/findRelevantMemories.ts +141 -0
  30. package/memdir/memdir.ts +511 -0
  31. package/memdir/memoryAge.ts +53 -0
  32. package/memdir/memoryScan.ts +94 -0
  33. package/memdir/memoryTypes.ts +271 -0
  34. package/memdir/paths.ts +291 -0
  35. package/memdir/teamMemPaths.ts +292 -0
  36. package/memdir/teamMemPrompts.ts +100 -0
  37. package/moreright/useMoreRight.tsx +26 -0
  38. package/native-ts/color-diff/index.ts +999 -0
  39. package/native-ts/file-index/index.ts +370 -0
  40. package/native-ts/yoga-layout/enums.ts +134 -0
  41. package/native-ts/yoga-layout/index.ts +2578 -0
  42. package/outputStyles/loadOutputStylesDir.ts +98 -0
  43. package/package.json +5 -42
  44. package/plugins/builtinPlugins.ts +159 -0
  45. package/plugins/bundled/index.ts +23 -0
  46. package/projectOnboardingState.ts +83 -0
  47. package/public/claude-files.png +0 -0
  48. package/public/leak-tweet.png +0 -0
  49. package/query/config.ts +46 -0
  50. package/query/deps.ts +40 -0
  51. package/query/stopHooks.ts +470 -0
  52. package/query/tokenBudget.ts +93 -0
  53. package/replLauncher.tsx +27 -0
  54. package/schemas/hooks.ts +222 -0
  55. package/screens/Doctor.tsx +575 -0
  56. package/screens/REPL.tsx +7107 -0
  57. package/screens/ResumeConversation.tsx +399 -0
  58. package/scripts/postinstall.js +90 -0
  59. package/server/createDirectConnectSession.ts +88 -0
  60. package/server/directConnectManager.ts +213 -0
  61. package/server/types.ts +57 -0
  62. package/setup.ts +477 -0
  63. package/stub_types.sh +13 -0
  64. package/tasks.ts +39 -0
  65. package/tools.ts +396 -0
  66. package/tsconfig.json +16 -0
  67. package/upstreamproxy/relay.ts +455 -0
  68. package/upstreamproxy/upstreamproxy.ts +285 -0
  69. package/vim/motions.ts +82 -0
  70. package/vim/operators.ts +556 -0
  71. package/vim/textObjects.ts +186 -0
  72. package/vim/transitions.ts +490 -0
  73. package/vim/types.ts +199 -0
  74. package/voice/voiceModeEnabled.ts +54 -0
  75. package/utils/bunBundleCompat.ts +0 -44
@@ -0,0 +1,213 @@
1
+ /* eslint-disable eslint-plugin-n/no-unsupported-features/node-builtins */
2
+
3
+ import type { SDKMessage } from '../entrypoints/agentSdkTypes.js'
4
+ import type {
5
+ SDKControlPermissionRequest,
6
+ StdoutMessage,
7
+ } from '../entrypoints/sdk/controlTypes.js'
8
+ import type { RemotePermissionResponse } from '../remote/RemoteSessionManager.js'
9
+ import { logForDebugging } from '../utils/debug.js'
10
+ import { jsonParse, jsonStringify } from '../utils/slowOperations.js'
11
+ import type { RemoteMessageContent } from '../utils/teleport/api.js'
12
+
13
+ export type DirectConnectConfig = {
14
+ serverUrl: string
15
+ sessionId: string
16
+ wsUrl: string
17
+ authToken?: string
18
+ }
19
+
20
+ export type DirectConnectCallbacks = {
21
+ onMessage: (message: SDKMessage) => void
22
+ onPermissionRequest: (
23
+ request: SDKControlPermissionRequest,
24
+ requestId: string,
25
+ ) => void
26
+ onConnected?: () => void
27
+ onDisconnected?: () => void
28
+ onError?: (error: Error) => void
29
+ }
30
+
31
+ function isStdoutMessage(value: unknown): value is StdoutMessage {
32
+ return (
33
+ typeof value === 'object' &&
34
+ value !== null &&
35
+ 'type' in value &&
36
+ typeof value.type === 'string'
37
+ )
38
+ }
39
+
40
+ export class DirectConnectSessionManager {
41
+ private ws: WebSocket | null = null
42
+ private config: DirectConnectConfig
43
+ private callbacks: DirectConnectCallbacks
44
+
45
+ constructor(config: DirectConnectConfig, callbacks: DirectConnectCallbacks) {
46
+ this.config = config
47
+ this.callbacks = callbacks
48
+ }
49
+
50
+ connect(): void {
51
+ const headers: Record<string, string> = {}
52
+ if (this.config.authToken) {
53
+ headers['authorization'] = `Bearer ${this.config.authToken}`
54
+ }
55
+ // Bun's WebSocket supports headers option but the DOM typings don't
56
+ this.ws = new WebSocket(this.config.wsUrl, {
57
+ headers,
58
+ } as unknown as string[])
59
+
60
+ this.ws.addEventListener('open', () => {
61
+ this.callbacks.onConnected?.()
62
+ })
63
+
64
+ this.ws.addEventListener('message', event => {
65
+ const data = typeof event.data === 'string' ? event.data : ''
66
+ const lines = data.split('\n').filter((l: string) => l.trim())
67
+
68
+ for (const line of lines) {
69
+ let raw: unknown
70
+ try {
71
+ raw = jsonParse(line)
72
+ } catch {
73
+ continue
74
+ }
75
+
76
+ if (!isStdoutMessage(raw)) {
77
+ continue
78
+ }
79
+ const parsed = raw
80
+
81
+ // Handle control requests (permission requests)
82
+ if (parsed.type === 'control_request') {
83
+ if (parsed.request.subtype === 'can_use_tool') {
84
+ this.callbacks.onPermissionRequest(
85
+ parsed.request,
86
+ parsed.request_id,
87
+ )
88
+ } else {
89
+ // Send an error response for unrecognized subtypes so the
90
+ // server doesn't hang waiting for a reply that never comes.
91
+ logForDebugging(
92
+ `[DirectConnect] Unsupported control request subtype: ${parsed.request.subtype}`,
93
+ )
94
+ this.sendErrorResponse(
95
+ parsed.request_id,
96
+ `Unsupported control request subtype: ${parsed.request.subtype}`,
97
+ )
98
+ }
99
+ continue
100
+ }
101
+
102
+ // Forward SDK messages (assistant, result, system, etc.)
103
+ if (
104
+ parsed.type !== 'control_response' &&
105
+ parsed.type !== 'keep_alive' &&
106
+ parsed.type !== 'control_cancel_request' &&
107
+ parsed.type !== 'streamlined_text' &&
108
+ parsed.type !== 'streamlined_tool_use_summary' &&
109
+ !(parsed.type === 'system' && parsed.subtype === 'post_turn_summary')
110
+ ) {
111
+ this.callbacks.onMessage(parsed)
112
+ }
113
+ }
114
+ })
115
+
116
+ this.ws.addEventListener('close', () => {
117
+ this.callbacks.onDisconnected?.()
118
+ })
119
+
120
+ this.ws.addEventListener('error', () => {
121
+ this.callbacks.onError?.(new Error('WebSocket connection error'))
122
+ })
123
+ }
124
+
125
+ sendMessage(content: RemoteMessageContent): boolean {
126
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
127
+ return false
128
+ }
129
+
130
+ // Must match SDKUserMessage format expected by `--input-format stream-json`
131
+ const message = jsonStringify({
132
+ type: 'user',
133
+ message: {
134
+ role: 'user',
135
+ content: content,
136
+ },
137
+ parent_tool_use_id: null,
138
+ session_id: '',
139
+ })
140
+ this.ws.send(message)
141
+ return true
142
+ }
143
+
144
+ respondToPermissionRequest(
145
+ requestId: string,
146
+ result: RemotePermissionResponse,
147
+ ): void {
148
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
149
+ return
150
+ }
151
+
152
+ // Must match SDKControlResponse format expected by StructuredIO
153
+ const response = jsonStringify({
154
+ type: 'control_response',
155
+ response: {
156
+ subtype: 'success',
157
+ request_id: requestId,
158
+ response: {
159
+ behavior: result.behavior,
160
+ ...(result.behavior === 'allow'
161
+ ? { updatedInput: result.updatedInput }
162
+ : { message: result.message }),
163
+ },
164
+ },
165
+ })
166
+ this.ws.send(response)
167
+ }
168
+
169
+ /**
170
+ * Send an interrupt signal to cancel the current request
171
+ */
172
+ sendInterrupt(): void {
173
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
174
+ return
175
+ }
176
+
177
+ // Must match SDKControlRequest format expected by StructuredIO
178
+ const request = jsonStringify({
179
+ type: 'control_request',
180
+ request_id: crypto.randomUUID(),
181
+ request: {
182
+ subtype: 'interrupt',
183
+ },
184
+ })
185
+ this.ws.send(request)
186
+ }
187
+
188
+ private sendErrorResponse(requestId: string, error: string): void {
189
+ if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
190
+ return
191
+ }
192
+ const response = jsonStringify({
193
+ type: 'control_response',
194
+ response: {
195
+ subtype: 'error',
196
+ request_id: requestId,
197
+ error,
198
+ },
199
+ })
200
+ this.ws.send(response)
201
+ }
202
+
203
+ disconnect(): void {
204
+ if (this.ws) {
205
+ this.ws.close()
206
+ this.ws = null
207
+ }
208
+ }
209
+
210
+ isConnected(): boolean {
211
+ return this.ws?.readyState === WebSocket.OPEN
212
+ }
213
+ }
@@ -0,0 +1,57 @@
1
+ import type { ChildProcess } from 'child_process'
2
+ import { z } from 'zod/v4'
3
+ import { lazySchema } from '../utils/lazySchema.js'
4
+
5
+ export const connectResponseSchema = lazySchema(() =>
6
+ z.object({
7
+ session_id: z.string(),
8
+ ws_url: z.string(),
9
+ work_dir: z.string().optional(),
10
+ }),
11
+ )
12
+
13
+ export type ServerConfig = {
14
+ port: number
15
+ host: string
16
+ authToken: string
17
+ unix?: string
18
+ /** Idle timeout for detached sessions (ms). 0 = never expire. */
19
+ idleTimeoutMs?: number
20
+ /** Maximum number of concurrent sessions. */
21
+ maxSessions?: number
22
+ /** Default workspace directory for sessions that don't specify cwd. */
23
+ workspace?: string
24
+ }
25
+
26
+ export type SessionState =
27
+ | 'starting'
28
+ | 'running'
29
+ | 'detached'
30
+ | 'stopping'
31
+ | 'stopped'
32
+
33
+ export type SessionInfo = {
34
+ id: string
35
+ status: SessionState
36
+ createdAt: number
37
+ workDir: string
38
+ process: ChildProcess | null
39
+ sessionKey?: string
40
+ }
41
+
42
+ /**
43
+ * Stable session key → session metadata. Persisted to ~/.claude/server-sessions.json
44
+ * so sessions can be resumed across server restarts.
45
+ */
46
+ export type SessionIndexEntry = {
47
+ /** Server-assigned session ID (matches the subprocess's claude session). */
48
+ sessionId: string
49
+ /** The claude transcript session ID for --resume. Same as sessionId for direct sessions. */
50
+ transcriptSessionId: string
51
+ cwd: string
52
+ permissionMode?: string
53
+ createdAt: number
54
+ lastActiveAt: number
55
+ }
56
+
57
+ export type SessionIndex = Record<string, SessionIndexEntry>