Skip to content

Xcode26.3#125

Merged
johnno1962 merged 11 commits intomainfrom
Xcode26.3
Apr 17, 2026
Merged

Xcode26.3#125
johnno1962 merged 11 commits intomainfrom
Xcode26.3

Conversation

@johnno1962
Copy link
Copy Markdown
Owner

@johnno1962 johnno1962 commented Mar 31, 2026

Log parsing fallback. May need to back-port to InjectionIII if EMIT_FRONTEND_COMMAND_LINES stops working.

# Conflicts:
#	App/InjectionNext/Info.plist
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 7 times, most recently from c1bfa8d to 6f045d4 Compare April 1, 2026 15:46
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 3 times, most recently from 77f94c1 to 543d978 Compare April 1, 2026 23:45
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the client↔server handshake to send the running app’s executable path (so the server can derive an app name), adjusts the SwiftPM target layout/module naming, and tweaks the file-watcher pattern as part of the “rework log parsing” effort noted in the PR description.

Changes:

  • Add a new InjectionResponse case (InjectionExecutable) and send the client executable path during connection.
  • Update the server to consume the new response and set Reloader.appName based on the executable.
  • Rename the SwiftPM target to InjectionBundle and update project/version metadata; extend watcher regex to include .o.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
Sources/InjectionNextC/include/InjectionClient.h Adds a new response enum case used in the socket protocol.
Sources/InjectionNext/InjectionNext.swift Sends the executable path to the server as part of initial connection metadata.
Package.swift Renames the SwiftPM target/module to InjectionBundle while keeping product name InjectionNext.
App/InjectionNext/InjectionServer.swift Handles the new .executable response and derives Reloader.appName.
App/InjectionNext/InjectionHybrid.swift Expands file-watcher injectable pattern to include .o files.
App/InjectionNext/Info.plist Increments build number.
App/InjectionNext.xcodeproj/project.pbxproj Bumps marketing version and sets module name for InjectionBundle target.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Sources/InjectionNextC/include/InjectionClient.h
Comment thread Package.swift
Comment thread App/InjectionNext/InjectionHybrid.swift
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 10 times, most recently from bc96a65 to bcaa6d7 Compare April 3, 2026 09:20
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 3 times, most recently from 8caebae to 6136594 Compare April 3, 2026 12:07
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 4 times, most recently from 91d4b4e to 31f5348 Compare April 3, 2026 17:28
@johnno1962 johnno1962 force-pushed the Xcode26.3 branch 5 times, most recently from fb084c6 to 2186111 Compare April 5, 2026 16:29
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 12 changed files in this pull request and generated 6 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread Package.swift
Comment thread App/InjectionNext/InjectionServer.swift
Comment thread App/InjectionNext/NextCompiler.swift
Comment thread App/InjectionNext/MonitorXcode.swift
Comment thread App/InjectionNext/FrontendServer.swift
Comment thread App/InjectionNext/InjectionServer.swift
* Add MCP server for AI-driven control of InjectionNext

- ControlServer: local TCP server (localhost:8919) that exposes app
  actions as JSON commands (watch project, enable devices, get status, etc.)
- LogBuffer: ring buffer capturing injection logs, compilation errors,
  and file watcher activity for AI consumption
- MCP server (Node.js): 13 tools exposing InjectionNext to AI agents
  via the Model Context Protocol (get_status, watch_project, get_logs, etc.)
- Hook log() and InjectionServer.log/error into LogBuffer for real-time
  debug console access

Made-with: Cursor

* Update README.md

* Address review: opt-in mcpServer default, harden ControlServer

- Add Defaults.mcpServer boolean (set via `defaults write`); ControlServer
  and LogBuffer only start when enabled.
- Make LogBuffer.shared optional; all call sites use optional chaining.
- Clamp get_logs limit to 0...500 to prevent negative/overflow traps.
- Add 64KB max request size guard on TCP read loop.
- Add zod as direct dependency and engines field in package.json.
- Update README with enable step and correct Node.js version.

Made-with: Cursor
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 20 out of 21 changed files in this pull request and generated 3 comments.

Files not reviewed (1)
  • mcp-server/package-lock.json: Language not supported

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +163 to +172
private func sendResponse(_ sock: Int32, success: Bool, data: [String: Any]? = nil, error: String? = nil) {
var response: [String: Any] = ["success": success]
if let error = error { response["error"] = error }
if let data = data { response["data"] = data }
guard let jsonData = try? JSONSerialization.data(withJSONObject: response),
let jsonStr = String(data: jsonData, encoding: .utf8) else { return }
let line = jsonStr + "\n"
_ = line.withCString { ptr in
send(sock, ptr, strlen(ptr), 0)
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sendResponse writes the entire JSON line with a single send() call. send() is allowed to return after writing only a prefix of the buffer (partial write), which can truncate responses and cause the Node client to fail JSON parsing. Consider looping until all bytes are written (and handle EPIPE/ECONNRESET) before returning.

Suggested change
private func sendResponse(_ sock: Int32, success: Bool, data: [String: Any]? = nil, error: String? = nil) {
var response: [String: Any] = ["success": success]
if let error = error { response["error"] = error }
if let data = data { response["data"] = data }
guard let jsonData = try? JSONSerialization.data(withJSONObject: response),
let jsonStr = String(data: jsonData, encoding: .utf8) else { return }
let line = jsonStr + "\n"
_ = line.withCString { ptr in
send(sock, ptr, strlen(ptr), 0)
}
private func sendAll(_ sock: Int32, data: Data) {
data.withUnsafeBytes { rawBuffer in
guard let baseAddress = rawBuffer.baseAddress else { return }
var bytesSent = 0
while bytesSent < rawBuffer.count {
let remaining = rawBuffer.count - bytesSent
let pointer = baseAddress.advanced(by: bytesSent)
let sent = send(sock, pointer, remaining, 0)
if sent > 0 {
bytesSent += sent
continue
}
if sent == -1 {
if errno == EINTR {
continue
}
if errno == EPIPE || errno == ECONNRESET {
return
}
}
return
}
}
}
private func sendResponse(_ sock: Int32, success: Bool, data: [String: Any]? = nil, error: String? = nil) {
var response: [String: Any] = ["success": success]
if let error = error { response["error"] = error }
if let data = data { response["data"] = data }
guard var jsonData = try? JSONSerialization.data(withJSONObject: response) else { return }
jsonData.append(UInt8(ascii: "\n"))
sendAll(sock, data: jsonData)

Copilot uses AI. Check for mistakes.
Comment on lines +188 to +241
private func executeAction(_ action: String, params: [String: Any]) -> ActionResult {
switch action {

case "status":
return getStatus()

case "watch_project":
guard let path = params["path"] as? String else {
return .fail("Missing 'path' parameter")
}
return watchProject(path: path)

case "stop_watching":
return stopWatching()

case "launch_xcode":
return launchXcode()

case "intercept_compiler":
return interceptCompiler()

case "enable_devices":
let enable = params["enable"] as? Bool ?? true
return enableDevices(enable: enable)

case "unhide_symbols":
return unhideSymbols()

case "get_last_error":
return getLastError()

case "prepare_swiftui_source":
return prepareSwiftUISource()

case "prepare_swiftui_project":
return prepareSwiftUIProject()

case "set_xcode_path":
guard let path = params["path"] as? String else {
return .fail("Missing 'path' parameter")
}
return setXcodePath(path: path)

case "get_logs":
let since = params["since"] as? TimeInterval ?? 0
let limit = max(0, min(params["limit"] as? Int ?? 200, 500))
return getLogs(since: since, limit: limit)

case "clear_logs":
return clearLogs()

default:
return .fail("Unknown action: \(action)")
}
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The control server exposes privileged actions (launch Xcode, start watchers, toggle devices, etc.) on a localhost TCP port with no authentication/authorization. Even though it is opt-in, any local process can connect and drive these actions once enabled. Consider requiring a shared secret/token (e.g., in UserDefaults/env) and rejecting requests missing/invalid credentials, or using a Unix domain socket with filesystem permissions.

Copilot uses AI. Check for mistakes.
Comment thread Package.swift
Comment on lines 9 to +31
@@ -21,13 +21,13 @@ let package = Package(
// Targets are the basic building blocks of a package, defining a module or a test suite.
// Targets can depend on other targets in this package and products from dependencies.
.target(
name: "InjectionNext", dependencies: ["InjectionNextC"],
swiftSettings: [.define("DEBUG_ONLY")]),
name: "InjectionBundle", dependencies: ["InjectionNextC"],
path: "Sources/InjectionNext", swiftSettings: [.define("DEBUG_ONLY")]),
.target(
name: "InjectionNextC",
cSettings: [.define("DEBUG_ONLY"), .define("FISHHOOK_EXPORT")]),
.testTarget(
name: "InjectionNextTests",
dependencies: ["InjectionNext"]),
dependencies: ["InjectionBundle"]),
Copy link

Copilot AI Apr 16, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The SwiftPM target was renamed from "InjectionNext" to "InjectionBundle", but the existing tests still import the module name (e.g. "@testable import InjectionNext"). This change will make the test target fail to compile unless the test imports are updated (or the target/module name is kept as InjectionNext).

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants