@p4code/cli 0.6.14 → 0.6.16
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/dist/bin.mjs +134 -23
- package/dist/client/assets/DiffPanel-D-49iCgp.js +98 -0
- package/dist/client/assets/{FilePreviewPanel-BZZA-eBw.js → FilePreviewPanel-BoVkA6v5.js} +4 -4
- package/dist/client/assets/PreviewPanel-BJleJ76o.js +2 -0
- package/dist/client/assets/PullRequestCodeTab-DcWaYtU6.js +251 -0
- package/dist/client/assets/{fileCommentAnnotations-BK_HySqs.js → fileCommentAnnotations-CgO_0-Tr.js} +2 -2
- package/dist/client/assets/{index-gmiM3V15.js → index-sXPBcrsQ.js} +245 -233
- package/dist/client/assets/previewAssetResource-CdRrwvdJ.js +48 -0
- package/dist/client/assets/{renderFileChildren--G0qrlMR.js → renderFileChildren-rNvuBJzO.js} +2 -2
- package/dist/client/assets/{toggle-group-qrC3KUiP.js → toggle-group-BPwLpAJP.js} +2 -2
- package/dist/client/index.html +2 -2
- package/dist/resource-monitor/darwin-arm64/p4-resource-monitor +0 -0
- package/dist/resource-monitor/darwin-x64/p4-resource-monitor +0 -0
- package/dist/resource-monitor/linux-x64/p4-resource-monitor +0 -0
- package/dist/resource-monitor/win32-x64/p4-resource-monitor.exe +0 -0
- package/package.json +1 -1
- package/dist/client/assets/DiffPanel-DPdh841e.js +0 -98
- package/dist/client/assets/PreviewPanel-DUW0nki3.js +0 -2
- package/dist/client/assets/PullRequestCodeTab-LhQpGqLu.js +0 -251
- package/dist/client/assets/previewAssetResource-DEZquWCb.js +0 -48
package/dist/bin.mjs
CHANGED
|
@@ -268,7 +268,7 @@ const make$124 = () => {
|
|
|
268
268
|
const layer$124 = Layer.sync(NetService, make$124);
|
|
269
269
|
//#endregion
|
|
270
270
|
//#region package.json
|
|
271
|
-
var version$1 = "0.6.
|
|
271
|
+
var version$1 = "0.6.16";
|
|
272
272
|
//#endregion
|
|
273
273
|
//#region src/config.ts
|
|
274
274
|
/**
|
|
@@ -9888,7 +9888,13 @@ const DeviceSession = Schema$1.Struct({
|
|
|
9888
9888
|
platform: DevicePlatform,
|
|
9889
9889
|
openedAt: Schema$1.String,
|
|
9890
9890
|
/** Opaque lifetime identity; absent only on servers predating guarded close. */
|
|
9891
|
-
leaseId: Schema$1.optional(DeviceId)
|
|
9891
|
+
leaseId: Schema$1.optional(DeviceId),
|
|
9892
|
+
/**
|
|
9893
|
+
* Server-resolved folder of the agent's thread. Apple-backed control opens the
|
|
9894
|
+
* Xcode project found here, because Xcode asks the user to approve an agent
|
|
9895
|
+
* only once it opens a project.
|
|
9896
|
+
*/
|
|
9897
|
+
workspaceRoot: Schema$1.optional(Schema$1.String)
|
|
9892
9898
|
});
|
|
9893
9899
|
const DeviceServiceState = Schema$1.Struct({
|
|
9894
9900
|
hosts: Schema$1.Array(DeviceHostSummary),
|
|
@@ -10165,7 +10171,8 @@ var DeviceOperationError = class extends Schema$1.TaggedErrorClass()("DeviceOper
|
|
|
10165
10171
|
"request_failed",
|
|
10166
10172
|
"invalid_payload",
|
|
10167
10173
|
"settings_failed",
|
|
10168
|
-
"hub_rejected"
|
|
10174
|
+
"hub_rejected",
|
|
10175
|
+
"agent_access_disabled"
|
|
10169
10176
|
]),
|
|
10170
10177
|
exitCode: Schema$1.optional(Schema$1.Number),
|
|
10171
10178
|
cause: Schema$1.Defect()
|
|
@@ -10176,7 +10183,8 @@ var DeviceOperationError = class extends Schema$1.TaggedErrorClass()("DeviceOper
|
|
|
10176
10183
|
request_failed: "Could not communicate with device support. Try refreshing devices.",
|
|
10177
10184
|
invalid_payload: "The device request could not be encoded.",
|
|
10178
10185
|
settings_failed: "Could not read or save device settings.",
|
|
10179
|
-
hub_rejected: "The device hub could not complete the request."
|
|
10186
|
+
hub_rejected: "The device hub could not complete the request.",
|
|
10187
|
+
agent_access_disabled: "Agent device access is off. Turn on Settings > Devices > Allow agents to control devices."
|
|
10180
10188
|
}[this.reason];
|
|
10181
10189
|
return `Device ${this.operation} failed: ${explanation}`;
|
|
10182
10190
|
}
|
|
@@ -11332,6 +11340,12 @@ const ServerSettings = Schema$1.Struct({
|
|
|
11332
11340
|
*/
|
|
11333
11341
|
enableUnpromptedSubagents: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
11334
11342
|
/**
|
|
11343
|
+
* Compression mode new threads start with. The composer writes the user's
|
|
11344
|
+
* last pick here, so the next new thread follows it; each thread keeps its
|
|
11345
|
+
* own mode once created.
|
|
11346
|
+
*/
|
|
11347
|
+
defaultCompressMode: CompressMode.pipe(Schema$1.withDecodingDefault(Effect.succeed(DEFAULT_COMPRESS_MODE))),
|
|
11348
|
+
/**
|
|
11335
11349
|
* Beta. Whether Fusion role rules travel once through the provider's
|
|
11336
11350
|
* session channel (Claude's system prompt, Codex's developer instructions)
|
|
11337
11351
|
* with a one-line reference on each message, or the legacy way: the full
|
|
@@ -11635,6 +11649,7 @@ const ServerSettingsPatch = Schema$1.Struct({
|
|
|
11635
11649
|
enableVerificationBeforeCompletion: Schema$1.optionalKey(Schema$1.Boolean),
|
|
11636
11650
|
enableRootCauseBeforeFix: Schema$1.optionalKey(Schema$1.Boolean),
|
|
11637
11651
|
enableUnpromptedSubagents: Schema$1.optionalKey(Schema$1.Boolean),
|
|
11652
|
+
defaultCompressMode: Schema$1.optionalKey(CompressMode),
|
|
11638
11653
|
enableOptimizedFusionPromptDelivery: Schema$1.optionalKey(Schema$1.Boolean),
|
|
11639
11654
|
enableFusionObservation: Schema$1.optionalKey(Schema$1.Boolean),
|
|
11640
11655
|
storageCleanup: Schema$1.optionalKey(Schema$1.Struct({
|
|
@@ -49538,13 +49553,21 @@ var XcodeMcpClient = class XcodeMcpClient {
|
|
|
49538
49553
|
throw error;
|
|
49539
49554
|
}
|
|
49540
49555
|
}
|
|
49541
|
-
|
|
49556
|
+
/**
|
|
49557
|
+
* `abandonAfterMs` gives up on a slow reply without closing the bridge; the
|
|
49558
|
+
* default timeout closes it, since a stuck bridge cannot be trusted.
|
|
49559
|
+
*/
|
|
49560
|
+
request(method, params, signal, abandonAfterMs) {
|
|
49542
49561
|
signal.throwIfAborted();
|
|
49543
49562
|
if (this.closed) return Promise.reject(/* @__PURE__ */ new Error("Device MCP session is closed. Select the device again."));
|
|
49544
49563
|
const id = ++this.sequence;
|
|
49545
49564
|
return new Promise((resolve, reject) => {
|
|
49546
49565
|
const abort = () => this.close(/* @__PURE__ */ new Error("Device MCP request cancelled. Select the device again."));
|
|
49547
|
-
const timer = setTimeout(() => this.close(/* @__PURE__ */ new Error("Device MCP timed out. Select the device again.")), REQUEST_TIMEOUT_MS$5)
|
|
49566
|
+
const timer = abandonAfterMs === void 0 ? setTimeout(() => this.close(/* @__PURE__ */ new Error("Device MCP timed out. Select the device again.")), REQUEST_TIMEOUT_MS$5) : setTimeout(() => {
|
|
49567
|
+
this.pending.delete(id);
|
|
49568
|
+
finish();
|
|
49569
|
+
reject(/* @__PURE__ */ new Error(`Device MCP ${method} did not answer in time.`));
|
|
49570
|
+
}, abandonAfterMs);
|
|
49548
49571
|
const finish = () => {
|
|
49549
49572
|
clearTimeout(timer);
|
|
49550
49573
|
signal.removeEventListener("abort", abort);
|
|
@@ -49568,7 +49591,7 @@ var XcodeMcpClient = class XcodeMcpClient {
|
|
|
49568
49591
|
}) + "\n");
|
|
49569
49592
|
});
|
|
49570
49593
|
}
|
|
49571
|
-
async call(name, args, signal) {
|
|
49594
|
+
async call(name, args, signal, options) {
|
|
49572
49595
|
if (!this.tools.has(name)) throw new Error(`Selected device MCP service does not expose ${name}. Check adapter capabilities and Xcode setup.`);
|
|
49573
49596
|
const redact = (error) => {
|
|
49574
49597
|
let message = error instanceof Error ? error.message : String(error);
|
|
@@ -49579,7 +49602,7 @@ var XcodeMcpClient = class XcodeMcpClient {
|
|
|
49579
49602
|
const result = objectValue(await this.request("tools/call", {
|
|
49580
49603
|
name,
|
|
49581
49604
|
arguments: args
|
|
49582
|
-
}, signal));
|
|
49605
|
+
}, signal, options?.abandonAfterMs));
|
|
49583
49606
|
const structured = objectValue(result.structuredContent);
|
|
49584
49607
|
if (result.isError === true || structured.didError === true) {
|
|
49585
49608
|
const detail = (Array.isArray(result.content) ? result.content : []).map((part) => objectValue(part).text).filter((part) => typeof part === "string").join("\n");
|
|
@@ -49781,6 +49804,15 @@ const REQUIRED_DEVICE_TOOLS = [
|
|
|
49781
49804
|
"DeviceInteractionSynthesize",
|
|
49782
49805
|
"DeviceInteractionEndSession"
|
|
49783
49806
|
];
|
|
49807
|
+
const XCODE_PROJECT_SEARCH_DEPTH = 3;
|
|
49808
|
+
const DISCOVERED_PROJECT_OPEN_WAIT_MS = 15e3;
|
|
49809
|
+
const XCODE_PROJECT_SKIPPED_DIRECTORIES = /* @__PURE__ */ new Set([
|
|
49810
|
+
"node_modules",
|
|
49811
|
+
"Pods",
|
|
49812
|
+
"DerivedData",
|
|
49813
|
+
"build",
|
|
49814
|
+
"Carthage"
|
|
49815
|
+
]);
|
|
49784
49816
|
const FRAME_PATTERN = /\{\{(-?[\d.]+),\s*(-?[\d.]+)\},\s*\{([\d.]+),\s*([\d.]+)\}\}/;
|
|
49785
49817
|
const HIT_PATTERN = /hitPoint:\s*\{(-?[\d.]+),\s*(-?[\d.]+)\}/;
|
|
49786
49818
|
const Capture = Schema$1.Struct({
|
|
@@ -49848,6 +49880,33 @@ function appleHierarchySnapshot(text, sequence) {
|
|
|
49848
49880
|
elements
|
|
49849
49881
|
};
|
|
49850
49882
|
}
|
|
49883
|
+
/**
|
|
49884
|
+
* Shallowest `.xcworkspace` under a thread's folder, else the shallowest
|
|
49885
|
+
* `.xcodeproj`. Bundles, dot folders and dependency trees are not searched.
|
|
49886
|
+
*/
|
|
49887
|
+
const findXcodeProject = (fs, root) => Effect.gen(function* () {
|
|
49888
|
+
let level = [root];
|
|
49889
|
+
for (let depth = 0; depth <= XCODE_PROJECT_SEARCH_DEPTH && level.length > 0; depth++) {
|
|
49890
|
+
const next = [];
|
|
49891
|
+
let project;
|
|
49892
|
+
for (const directory of level) {
|
|
49893
|
+
const names = yield* fs.readDirectory(directory).pipe(Effect.orElseSucceed(() => []));
|
|
49894
|
+
for (const name of names.toSorted()) {
|
|
49895
|
+
const path = `${directory}/${name}`;
|
|
49896
|
+
if (name.endsWith(".xcworkspace")) return path;
|
|
49897
|
+
if (name.endsWith(".xcodeproj")) {
|
|
49898
|
+
project ??= path;
|
|
49899
|
+
continue;
|
|
49900
|
+
}
|
|
49901
|
+
if (name.startsWith(".") || XCODE_PROJECT_SKIPPED_DIRECTORIES.has(name)) continue;
|
|
49902
|
+
const info = yield* fs.stat(path).pipe(Effect.option);
|
|
49903
|
+
if (Option.isSome(info) && info.value.type === "Directory") next.push(path);
|
|
49904
|
+
}
|
|
49905
|
+
}
|
|
49906
|
+
if (project) return project;
|
|
49907
|
+
level = next;
|
|
49908
|
+
}
|
|
49909
|
+
});
|
|
49851
49910
|
function createAppleDeviceAdapter(input) {
|
|
49852
49911
|
const sessions = /* @__PURE__ */ new Map();
|
|
49853
49912
|
const fail = (operation) => (cause) => new DeviceOperationError({
|
|
@@ -49870,7 +49929,9 @@ function createAppleDeviceAdapter(input) {
|
|
|
49870
49929
|
}
|
|
49871
49930
|
}).catch(() => {});
|
|
49872
49931
|
};
|
|
49873
|
-
const
|
|
49932
|
+
const workspaceFor = (session) => input.workspacePath !== void 0 || !session.workspaceRoot || session.leaseId !== void 0 && sessions.has(session.leaseId) ? Effect.succeed(input.workspacePath) : findXcodeProject(input.fs, session.workspaceRoot);
|
|
49933
|
+
const get = (session) => Effect.flatMap(workspaceFor(session), (workspace) => open(session, workspace));
|
|
49934
|
+
const open = (session, workspace) => Effect.tryPromise({
|
|
49874
49935
|
try: async (signal) => {
|
|
49875
49936
|
if (session.hostId !== "local" || session.platform !== "ios" || !session.leaseId) throw new Error("Apple MCP requires an exact local iOS device lease.");
|
|
49876
49937
|
let pending = sessions.get(session.leaseId);
|
|
@@ -49885,6 +49946,7 @@ function createAppleDeviceAdapter(input) {
|
|
|
49885
49946
|
const missing = REQUIRED_DEVICE_TOOLS.filter((tool) => !client.tools.has(tool));
|
|
49886
49947
|
if (missing.length > 0) throw new Error(`Selected Xcode lacks required device tools: ${missing.join(", ")}. No device session was opened.`);
|
|
49887
49948
|
if (input.workspacePath) await client.call("XcodeOpenWorkspace", { path: input.workspacePath }, signal);
|
|
49949
|
+
else if (workspace) await client.call("XcodeOpenWorkspace", { path: workspace }, signal, { abandonAfterMs: DISCOVERED_PROJECT_OPEN_WAIT_MS }).catch(() => void 0);
|
|
49888
49950
|
const opened = Schema$1.decodeUnknownSync(Session)(appleMcpData(await client.call("DeviceInteractionStartSession", {
|
|
49889
49951
|
deviceIdentifier: session.deviceId,
|
|
49890
49952
|
sessionIdentifier: `P4 Device ${session.threadId.slice(0, 8)}`
|
|
@@ -49956,7 +50018,7 @@ function createAppleDeviceAdapter(input) {
|
|
|
49956
50018
|
const permission = objectValue(status.permission);
|
|
49957
50019
|
if ((Array.isArray(permission.pendingAgentApprovals) ? permission.pendingAgentApprovals : []).some((item) => objectValue(objectValue(objectValue(objectValue(item).subject).agent)._0).name === "p4code-device-adapter")) return "Apple Xcode is waiting for approval of p4code-device-adapter and its project folder. Approve the pending request in Xcode, then select the device again. P4 cannot grant this approval automatically.";
|
|
49958
50020
|
if (status.running === false) return "Apple MCP service is not running. Open the selected Xcode project or configure its headless service, then select the device again.";
|
|
49959
|
-
return "Apple MCP did not respond
|
|
50021
|
+
return "Apple MCP refused or did not respond. Xcode asks to approve p4code-device-adapter only when P4 opens an Xcode project: use a thread whose folder contains an .xcworkspace or .xcodeproj (or set P4CODE_APPLE_MCP_WORKSPACE), approve the prompt in Xcode, then select the device again.";
|
|
49960
50022
|
}).pipe(Effect.orElseSucceed(() => "Apple MCP did not respond. Check Xcode agent/folder permissions and service status.")),
|
|
49961
50023
|
discover: Effect.gen(function* () {
|
|
49962
50024
|
const result = yield* input.run("xcrun", [
|
|
@@ -51583,7 +51645,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
51583
51645
|
yield* (yield* initialize).refresh;
|
|
51584
51646
|
if (access === "agent" && !state.agentAccessEnabled) return yield* new DeviceOperationError({
|
|
51585
51647
|
operation: "list",
|
|
51586
|
-
reason: "
|
|
51648
|
+
reason: "agent_access_disabled",
|
|
51587
51649
|
cause: "Agent device access is disabled."
|
|
51588
51650
|
});
|
|
51589
51651
|
const ids = enabled ? state.hosts.map((host) => host.id) : [];
|
|
@@ -51689,7 +51751,8 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
51689
51751
|
deviceId: found.device.id,
|
|
51690
51752
|
platform: found.device.platform,
|
|
51691
51753
|
openedAt,
|
|
51692
|
-
leaseId: NodeCrypto.randomUUID()
|
|
51754
|
+
leaseId: NodeCrypto.randomUUID(),
|
|
51755
|
+
...value.workspaceRoot ? { workspaceRoot: value.workspaceRoot } : {}
|
|
51693
51756
|
};
|
|
51694
51757
|
yield* closeCommands(sessionsToClose(state.sessions, session));
|
|
51695
51758
|
yield* update((current) => ({
|
|
@@ -57972,6 +58035,7 @@ const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* (fusion
|
|
|
57972
58035
|
//#region src/mcp/DeviceInvocation.ts
|
|
57973
58036
|
const isDeviceToolUnavailableError = Schema$1.is(DeviceToolUnavailableError);
|
|
57974
58037
|
const isDeviceActionUnavailableError = Schema$1.is(DeviceActionUnavailableError);
|
|
58038
|
+
const isDeviceOperationError = Schema$1.is(DeviceOperationError);
|
|
57975
58039
|
/** Internal bridge; tool payloads never choose thread identity or daemon credentials. */
|
|
57976
58040
|
const withDeviceInvocation = (execute, capability = "devices") => Effect.gen(function* () {
|
|
57977
58041
|
const invocation = yield* McpInvocationContext;
|
|
@@ -57979,9 +58043,21 @@ const withDeviceInvocation = (execute, capability = "devices") => Effect.gen(fun
|
|
|
57979
58043
|
const lifetime = invocation.authorizationLifetime;
|
|
57980
58044
|
const denied = () => new DeviceToolUnavailableError({ reason: "Device command unavailable or authorization changed." });
|
|
57981
58045
|
if (!invocation.capabilities.has(capability) || !lifetime?.revocation || lifetime.revoked) return yield* denied();
|
|
57982
|
-
const work = execute(service, invocation.threadId).pipe(Effect.tap(() => lifetime.revoked ? Effect.fail(denied()) : Effect.void), Effect.mapError((error) => isDeviceToolUnavailableError(error) || isDeviceActionUnavailableError(error) ? error : denied()));
|
|
58046
|
+
const work = execute(service, invocation.threadId).pipe(Effect.tap(() => lifetime.revoked ? Effect.fail(denied()) : Effect.void), Effect.mapError((error) => isDeviceToolUnavailableError(error) || isDeviceActionUnavailableError(error) ? error : isDeviceOperationError(error) && error.reason === "agent_access_disabled" ? new DeviceToolUnavailableError({ reason: error.message }) : denied()));
|
|
57983
58047
|
return yield* Effect.raceFirst(work, Deferred.await(lifetime.revocation).pipe(Effect.andThen(Effect.fail(denied()))));
|
|
57984
58048
|
});
|
|
58049
|
+
/**
|
|
58050
|
+
* The thread's worktree, else its project root, for opening a device session.
|
|
58051
|
+
* Unreadable projections yield nothing: the session still opens without it.
|
|
58052
|
+
*/
|
|
58053
|
+
const threadWorkspaceRoot = (threadId) => Effect.gen(function* () {
|
|
58054
|
+
const query = yield* ProjectionSnapshotQuery;
|
|
58055
|
+
const thread = yield* query.getThreadShellById(threadId);
|
|
58056
|
+
if (Option.isNone(thread)) return void 0;
|
|
58057
|
+
if (thread.value.worktreePath) return thread.value.worktreePath;
|
|
58058
|
+
const project = yield* query.getProjectShellById(thread.value.projectId);
|
|
58059
|
+
return Option.isSome(project) ? project.value.workspaceRoot : void 0;
|
|
58060
|
+
}).pipe(Effect.orElseSucceed(() => void 0));
|
|
57985
58061
|
const withDeviceSession = (target, execute) => withDeviceInvocation((service, threadId) => service.withAgentCommand({
|
|
57986
58062
|
hostId: target.hostId,
|
|
57987
58063
|
deviceId: target.deviceId,
|
|
@@ -58014,6 +58090,7 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
58014
58090
|
const screenshots = yield* DeviceScreenshot;
|
|
58015
58091
|
const commands = yield* DeviceCommandProxy;
|
|
58016
58092
|
const http = yield* HttpClient.HttpClient;
|
|
58093
|
+
const snapshots = yield* ProjectionSnapshotQuery;
|
|
58017
58094
|
const stale = () => new DeviceOperationError({
|
|
58018
58095
|
operation: "command",
|
|
58019
58096
|
reason: "request_failed",
|
|
@@ -58034,11 +58111,13 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
58034
58111
|
const device = state.devices.find((device) => device.hostId === input.hostId && device.id === input.deviceId && device.platform === input.platform);
|
|
58035
58112
|
if (!device) return yield* stale();
|
|
58036
58113
|
if (device.physical) return yield* new DeviceToolUnavailableError({ reason: "Physical-device UI control is not supported by this adapter. Pairing, trust, Developer Mode and signing must be configured separately; use supported device-management workflows." });
|
|
58114
|
+
const workspaceRoot = yield* threadWorkspaceRoot(threadId).pipe(Effect.provideService(ProjectionSnapshotQuery, snapshots));
|
|
58037
58115
|
const session = yield* service.agentOpen({
|
|
58038
58116
|
threadId,
|
|
58039
58117
|
hostId: input.hostId,
|
|
58040
58118
|
deviceId: input.deviceId,
|
|
58041
|
-
platform: input.platform
|
|
58119
|
+
platform: input.platform,
|
|
58120
|
+
...workspaceRoot ? { workspaceRoot } : {}
|
|
58042
58121
|
});
|
|
58043
58122
|
if (!session.leaseId) return yield* stale();
|
|
58044
58123
|
return {
|
|
@@ -69723,6 +69802,13 @@ const NARRATE_BEFORE_TOOLS_PROMPT = "Before each turn's first tool call, state n
|
|
|
69723
69802
|
*/
|
|
69724
69803
|
const SUBAGENTS_ALLOWED_PROMPT = "You may spawn Task subagents without asking; this overrides earlier request-only rules. Use for bounded search/review whose result is far smaller than required reading. Single-file answer/edit stays inline.";
|
|
69725
69804
|
const SUBAGENTS_ON_REQUEST_PROMPT = "Never spawn Task subagents unless user asks; this overrides earlier proactive permission. Work inline; say when delegation would have been better.";
|
|
69805
|
+
/**
|
|
69806
|
+
* Appended to ordinary (non-Fusion) sessions. Fusion role prompts already tell
|
|
69807
|
+
* both roles to follow applicable instructions and load memories and skills;
|
|
69808
|
+
* without the same line an ordinary thread treats the user's memory store as
|
|
69809
|
+
* optional background it may skip.
|
|
69810
|
+
*/
|
|
69811
|
+
const INSTRUCTIONS_AND_MEMORY_PROMPT = "Follow applicable global and project instructions, and load relevant memories and skills on demand. When ~/.agent-memory exists, read its INDEX.md and the entries it points you to before acting.";
|
|
69726
69812
|
//#endregion
|
|
69727
69813
|
//#region src/provider/Layers/ClaudeAdapter.ts
|
|
69728
69814
|
/**
|
|
@@ -70398,6 +70484,22 @@ const CLAUDE_SETTING_SOURCES = [
|
|
|
70398
70484
|
"project",
|
|
70399
70485
|
"local"
|
|
70400
70486
|
];
|
|
70487
|
+
/**
|
|
70488
|
+
* Claude user-scope MCP servers this session already receives under their
|
|
70489
|
+
* `p4-user-` alias, as `deniedMcpServers` entries.
|
|
70490
|
+
*
|
|
70491
|
+
* The `user` setting source still loads the originals from `~/.claude.json`,
|
|
70492
|
+
* where Claude has no credential for a server p4code authorized. An OAuth
|
|
70493
|
+
* server then appears twice, once working and once as "needs authentication",
|
|
70494
|
+
* and the agent believes the service is unavailable. Denying each original by
|
|
70495
|
+
* name leaves the working alias as the only copy. The deny matches by name in
|
|
70496
|
+
* every Claude scope, so a same-named project server is dropped too.
|
|
70497
|
+
*/
|
|
70498
|
+
function claudeShadowedUserScopeMcpServers(sessionServerNames) {
|
|
70499
|
+
const prefix = mcpUserScopeSessionName("");
|
|
70500
|
+
const names = new Set(sessionServerNames);
|
|
70501
|
+
return sessionServerNames.filter((name) => name.startsWith(prefix)).map((name) => name.slice(prefix.length)).filter((original) => original.length > 0 && !names.has(original)).map((serverName) => ({ serverName }));
|
|
70502
|
+
}
|
|
70401
70503
|
function buildPromptText(input, boundInstanceId, customModels = [], manifest) {
|
|
70402
70504
|
const rawEffort = input.modelSelection?.instanceId === boundInstanceId ? getModelSelectionStringOptionValue(input.modelSelection, "effort") : null;
|
|
70403
70505
|
const caps = getClaudeModelCapabilities(input.modelSelection?.instanceId === boundInstanceId ? input.modelSelection.model : void 0, customModels, manifest);
|
|
@@ -72433,14 +72535,16 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
72433
72535
|
}[input.runtimeMode];
|
|
72434
72536
|
const disabledSkills = options?.resolveDisabledSkills === void 0 ? [] : yield* options.resolveDisabledSkills;
|
|
72435
72537
|
const skillOverrides = disabledSkills.length === 0 ? void 0 : buildSkillOverrides(disabledSkills, yield* discoverClaudeSkills(claudeSettings, input.cwd, claudeEnvironment).pipe(Effect.provideService(FileSystem.FileSystem, fileSystem), Effect.provideService(Path$1.Path, path)));
|
|
72538
|
+
const mcpSession = readMcpProviderSession(input.threadId);
|
|
72539
|
+
const registeredMcpServers = Object.fromEntries(Object.entries(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers(input.cwd)).filter(([name]) => !providerMcpReservedNames().has(name)));
|
|
72540
|
+
const deniedMcpServers = claudeShadowedUserScopeMcpServers([...Object.keys(registeredMcpServers), ...providerMcpReservedNames()]);
|
|
72436
72541
|
const settings = {
|
|
72437
72542
|
...typeof thinking === "boolean" ? { alwaysThinkingEnabled: thinking } : {},
|
|
72438
72543
|
...fastMode ? { fastMode: true } : {},
|
|
72439
72544
|
...ultracode ? { ultracode: true } : {},
|
|
72440
|
-
...skillOverrides ? { skillOverrides } : {}
|
|
72545
|
+
...skillOverrides ? { skillOverrides } : {},
|
|
72546
|
+
...deniedMcpServers.length > 0 ? { deniedMcpServers } : {}
|
|
72441
72547
|
};
|
|
72442
|
-
const mcpSession = readMcpProviderSession(input.threadId);
|
|
72443
|
-
const registeredMcpServers = Object.fromEntries(Object.entries(options?.resolveMcpServers === void 0 ? {} : yield* options.resolveMcpServers(input.cwd)).filter(([name]) => !providerMcpReservedNames().has(name)));
|
|
72444
72548
|
const narrateBeforeTools = options?.resolveToolCallNarration === void 0 ? DEFAULT_SERVER_SETTINGS.enableToolCallNarration : yield* options.resolveToolCallNarration;
|
|
72445
72549
|
const guardrailSettings = options?.resolveGuardrailPrompts === void 0 ? {
|
|
72446
72550
|
enableVerificationBeforeCompletion: DEFAULT_SERVER_SETTINGS.enableVerificationBeforeCompletion,
|
|
@@ -72461,7 +72565,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
72461
72565
|
...narrateBeforeTools ? [NARRATE_BEFORE_TOOLS_PROMPT] : [],
|
|
72462
72566
|
...guardrailPromptsFor(guardrailSettings),
|
|
72463
72567
|
unpromptedSubagents ? SUBAGENTS_ALLOWED_PROMPT : SUBAGENTS_ON_REQUEST_PROMPT,
|
|
72464
|
-
...input.fusionRole !== void 0 ? [fusionRoleInstructionsWith(input.fusionRole, "claudeAgent", fusionPromptSettings)] : [],
|
|
72568
|
+
...input.fusionRole !== void 0 ? [fusionRoleInstructionsWith(input.fusionRole, "claudeAgent", fusionPromptSettings)] : [INSTRUCTIONS_AND_MEMORY_PROMPT],
|
|
72465
72569
|
...fusionLeanContextApplies(fusionContextPolicy) ? [FUSION_SAFETY_KERNEL] : [],
|
|
72466
72570
|
...compressRuleset !== void 0 ? [compressRuleset] : []
|
|
72467
72571
|
].join("\n\n");
|
|
@@ -133150,6 +133254,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
|
|
|
133150
133254
|
reason: plan.reason
|
|
133151
133255
|
});
|
|
133152
133256
|
const modelSelection = plan.model;
|
|
133257
|
+
const compressMode = yield* serverSettings.getSettings.pipe(Effect.map((settings) => settings.defaultCompressMode), Effect.orElseSucceed(() => DEFAULT_COMPRESS_MODE));
|
|
133153
133258
|
const threadId = ThreadId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
|
|
133154
133259
|
const createdAt = yield* nowIso$2;
|
|
133155
133260
|
const threadTitle = buildTaskThreadTitle(task.title);
|
|
@@ -133174,7 +133279,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
|
|
|
133174
133279
|
titleSeed: threadTitle,
|
|
133175
133280
|
runtimeMode: DEFAULT_RUNTIME_MODE$2,
|
|
133176
133281
|
interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
|
|
133177
|
-
compressMode
|
|
133282
|
+
compressMode,
|
|
133178
133283
|
unpromptedSubagents: true,
|
|
133179
133284
|
bootstrap: { createThread: {
|
|
133180
133285
|
projectId: plan.projectId,
|
|
@@ -133182,7 +133287,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
|
|
|
133182
133287
|
modelSelection,
|
|
133183
133288
|
runtimeMode: DEFAULT_RUNTIME_MODE$2,
|
|
133184
133289
|
interactionMode: DEFAULT_PROVIDER_INTERACTION_MODE,
|
|
133185
|
-
compressMode
|
|
133290
|
+
compressMode,
|
|
133186
133291
|
unpromptedSubagents: true,
|
|
133187
133292
|
branch: null,
|
|
133188
133293
|
worktreePath: null,
|
|
@@ -133875,7 +133980,7 @@ const ProviderAdapterRegistryLive = Layer.effect(ProviderAdapterRegistry, makePr
|
|
|
133875
133980
|
//#endregion
|
|
133876
133981
|
//#region src/provider/ComputerUsePrompts.ts
|
|
133877
133982
|
/** Routing guidance is injected only when the session has P4's Computer Use endpoint. */
|
|
133878
|
-
const COMPUTER_USE_ROUTING_PROMPT = "P4 Computer Use is available for this session through the cua_repl MCP server. When you use it for a native desktop app, do not substitute AppleScript or shell automation unless the user explicitly requests that path. For a named app, start directly with const app = await cua.getApp(exactNameOrBundleId); read the automatically returned state/image and stop if it answers the request. Reuse the handle and batch safe actions; do not repeat selection or unchanged state. For Device Hub, simulator, emulator, or connected-device requests, use cua.listDevices() once, then cua.getDevice({hostId,deviceId,platform}) with exact discovered IDs, unless the user explicitly requested a different route such as simctl. Selection already emits initial device state. Reuse its handle; do not print the handle or repeat that state before acting. Never substitute macOS getApp('Simulator'). Device hosts are scoped to this provider environment and can differ from the desktop host. If device discovery, opening, inspection, or interaction reports missing permission or unavailable control, stop P4 device interaction and report the exact limitation. Do not silently retry through screenshots, shell simctl, Xcode tools, or another MCP server; an explicit user request for one of those routes is separate authorization to use it. Do not call getState/getApp, control the P4 desktop app, or open device settings to work around a device API failure. Missing consent, unavailable devices, or unsupported operations are P4 limitations to report, never permission to switch P4 hosts or bypass the tool.";
|
|
133983
|
+
const COMPUTER_USE_ROUTING_PROMPT = "P4 Computer Use is available for this session through the cua_repl MCP server. When you use it for a native desktop app, do not substitute AppleScript or shell automation unless the user explicitly requests that path. For a named app, start directly with const app = await cua.getApp(exactNameOrBundleId); read the automatically returned state/image and stop if it answers the request. Reuse the handle and batch safe actions; do not repeat selection or unchanged state. For Device Hub, simulator, emulator, or connected-device requests, use cua.listDevices() once, then cua.getDevice({hostId,deviceId,platform}) with exact discovered IDs, unless the user explicitly requested a different route such as simctl. Selection already emits initial device state. Reuse its handle; do not print the handle or repeat that state before acting. Never substitute macOS getApp('Simulator'). Device hosts are scoped to this provider environment and can differ from the desktop host. If device discovery, opening, inspection, or interaction reports missing permission or unavailable control, stop P4 device interaction and report the exact limitation. Do not silently retry through screenshots, shell simctl, Xcode tools, or another MCP server; an explicit user request for one of those routes, including a standing fallback authorization in the user's global or project instructions, is separate authorization to use it; report the P4 error and the fallback you used. Do not call getState/getApp, control the P4 desktop app, or open device settings to work around a device API failure. Missing consent, unavailable devices, or unsupported operations are P4 limitations to report, never on their own permission to switch P4 hosts or bypass the tool.";
|
|
133879
133984
|
/** The routing note, naming the server the way this session's provider sees it. */
|
|
133880
133985
|
function withComputerUseRouting(input, enabled, serverName = "cua_repl") {
|
|
133881
133986
|
const prompt = serverName === "cua_repl" ? COMPUTER_USE_ROUTING_PROMPT : COMPUTER_USE_ROUTING_PROMPT.replace("the cua_repl MCP server", `the ${serverName} MCP server`);
|
|
@@ -135370,7 +135475,11 @@ const DeviceOpenTool = Tool.make("device_open", {
|
|
|
135370
135475
|
parameters: DeviceToolOpenInput,
|
|
135371
135476
|
success: DeviceToolOpenResult,
|
|
135372
135477
|
failure: DeviceToolError,
|
|
135373
|
-
dependencies: [
|
|
135478
|
+
dependencies: [
|
|
135479
|
+
McpInvocationContext,
|
|
135480
|
+
DeviceService,
|
|
135481
|
+
ProjectionSnapshotQuery
|
|
135482
|
+
]
|
|
135374
135483
|
}).annotate(Tool.Title, "Open device").annotate(Tool.Readonly, false);
|
|
135375
135484
|
const DeviceCloseTool = Tool.make("device_close", {
|
|
135376
135485
|
description: "Close this thread's device sessions on the named host. Omitted device closes all sessions on that host only. Optional shutdown powers off the selected devices and closes their other viewing sessions.",
|
|
@@ -135482,11 +135591,13 @@ const DeviceToolkitHandlersLive = DeviceToolkit.toLayer({
|
|
|
135482
135591
|
try: () => selectDevice(state, threadId, value),
|
|
135483
135592
|
catch: () => new DeviceToolUnavailableError({ reason: "Choose an explicit platform/device from device_list on the requested host." })
|
|
135484
135593
|
});
|
|
135594
|
+
const workspaceRoot = yield* threadWorkspaceRoot(threadId);
|
|
135485
135595
|
const session = yield* service.agentOpen({
|
|
135486
135596
|
threadId,
|
|
135487
135597
|
hostId: value.hostId,
|
|
135488
135598
|
deviceId: selected.id,
|
|
135489
|
-
platform: selected.platform
|
|
135599
|
+
platform: selected.platform,
|
|
135600
|
+
...workspaceRoot ? { workspaceRoot } : {}
|
|
135490
135601
|
});
|
|
135491
135602
|
const current = yield* service.state;
|
|
135492
135603
|
const device = current.devices.find((device) => device.hostId === session.hostId && device.id === session.deviceId && device.platform === session.platform);
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import{r as e}from"./rolldown-runtime-QTnfLwEv.js";import{n as t,r as n,t as r}from"./compiler-runtime-CLAvuQ-D.js";import{$a as i,$u as a,Ba as o,Cl as s,Cn as c,Dt as l,Eu as ee,Ga as te,Kl as u,Kr as ne,La as d,Qa as f,Qr as re,Sl as p,Vr as m,Wa as h,Xa as ie,Za as g,_t as _,b as v,bu as ae,ct as y,eo as b,gt as x,h as S,hu as C,lu as w,vn as oe,wl as T,xl as E,yt as D}from"./previewAssetResource-CdRrwvdJ.js";import{a as O,c as se,i as k,n as A,o as j,r as M,s as ce,t as le}from"./toggle-group-BPwLpAJP.js";import{A as ue,Fr as de,J as fe,Lr as pe,M as N,Mr as me,Nr as he,Rr as ge,Y as _e,_ as ve,ar as ye,cr as be,ct as xe,dr as Se,dt as Ce,ft as P,h as we,ir as Te,j as Ee,jr as De,k as Oe,lr as ke,lt as Ae,nr as je,oi as Me,or as Ne,ot as Pe,pr as Fe,rr as Ie,si as Le,sr as Re,st as ze,ut as Be,yr as Ve}from"./index-sXPBcrsQ.js";import{a as He,n as Ue}from"./fileCommentAnnotations-CgO_0-Tr.js";var We=T(`pilcrow`,[[`path`,{d:`M13 4v16`,key:`8vvj80`}],[`path`,{d:`M17 4v16`,key:`7dpous`}],[`path`,{d:`M19 4H9.5a4.5 4.5 0 0 0 0 9H13`,key:`sh4n9v`}]]),F=e(n(),1);function Ge({threadRef:e,filePath:t,activeCwd:n,openInEditor:r,openFileSurface:i}){if(e){if(i){i(t);return}y.getState().openFile(e,t);return}r(n?S(t,n):t)}var I=r();function Ke(e,t){let n=(0,I.c)(4),r=Se(e,t),i;return n[0]!==r.data||n[1]!==r.error||n[2]!==r.isPending?(i={data:r.data,error:r.error,isPending:r.isPending},n[0]=r.data,n[1]=r.error,n[2]=r.isPending,n[3]=i):i=n[3],i}var L=t(),qe=[];function Je(e){return(e.endSide??e.side)===`deletions`?`deletions`:`additions`}function R(e,t,n){let r=Je(t),i=e.findIndex(e=>e.side===r&&e.lineNumber===t.end);return i<0?[...e,{side:r,lineNumber:t.end,metadata:{entries:[n]}}]:e.map((e,t)=>t===i?{...e,metadata:{entries:[...e.metadata.entries,n]}}:e)}function Ye(e){let t=(0,I.c)(50),{files:n,sectionId:r,sectionTitle:i,composerDraftTarget:a,options:o,viewerRef:s,className:c,renderHeaderPrefix:l}=e,ee=m(Qe),te=m(B),u;t[0]===a?u=t[1]:(u=e=>e.getComposerDraft(a)?.reviewComments??qe,t[0]=a,t[1]=u);let d=m(u),[f,p]=(0,F.useState)(null),[h,ie]=(0,F.useState)(null),g;t[2]===n?g=t[3]:(g=new Map(n.map(Ze)),t[2]=n,t[3]=g);let _=g,v;if(t[4]!==h||t[5]!==n||t[6]!==d||t[7]!==r){let e;t[9]!==h||t[10]!==d||t[11]!==r?(e=e=>{let{fileDiff:t,filePath:n,fileKey:i,collapsed:a}=e,o=d.filter(e=>e.sectionId===r&&e.filePath===n&&(e.fenceLanguage??`diff`)===`diff`).reduce((e,n)=>{let r=re(t,n);return r?R(e,r,{id:n.id,kind:`comment`,range:r,rangeLabel:n.rangeLabel,text:n.text}):e},[]),s=h?.fileKey===i?[...o,h.annotation]:o;return{id:i,type:`diff`,fileDiff:t,annotations:s,collapsed:a,version:ze(`${a?`1`:`0`}:${s.flatMap(z).join(`:`)}`)}},t[9]=h,t[10]=d,t[11]=r,t[12]=e):e=t[12],v=n.map(e),t[4]=h,t[5]=n,t[6]=d,t[7]=r,t[8]=v}else v=t[8];let ae=v,y;t[13]!==a||t[14]!==h?.annotation||t[15]!==te?(y=e=>{p(null),h?.annotation.metadata.entries.some(t=>t.id===e)?ie(null):te(a,e)},t[13]=a,t[14]=h?.annotation,t[15]=te,t[16]=y):y=t[16];let b=y,x;t[17]!==ee||t[18]!==a||t[19]!==h||t[20]!==_||t[21]!==r||t[22]!==i?(x=(e,t)=>{let n=h?.annotation.metadata.entries.find(t=>t.id===e),o=h?_.get(h.fileKey):void 0;if(!n||!o)return;let s=ne({id:n.id,sectionId:r,sectionTitle:i,filePath:o.filePath,fileDiff:o.fileDiff,range:n.range,text:t});s&&ee(a,s),p(null),ie(null)},t[17]=ee,t[18]=a,t[19]=h,t[20]=_,t[21]=r,t[22]=i,t[23]=x):x=t[23];let S=x,C;t[24]!==_||t[25]!==r||t[26]!==i?(C=(e,t)=>{if(!e)return;let n=t.item;if(n.type!==`diff`)return;let a=_.get(n.id);if(!a)return;let o=Ue(),s=ne({id:o,sectionId:r,sectionTitle:i,filePath:a.filePath,fileDiff:a.fileDiff,range:e,text:``});s&&ie({fileKey:n.id,annotation:{side:Je(e),lineNumber:e.end,metadata:{entries:[{id:o,kind:`draft`,range:e,rangeLabel:s.rangeLabel,text:``}]}}})},t[24]=_,t[25]=r,t[26]=i,t[27]=C):C=t[27];let w=C,oe=h!==null,T;t[28]===s?T=t[29]:(T=s?{ref:s}:{},t[28]=s,t[29]=T);let E;t[30]===c?E=t[31]:(E=c?{className:c}:{},t[30]=c,t[31]=E);let D=!oe,se=!oe,k;t[32]!==w||t[33]!==o||t[34]!==se||t[35]!==D?(k={...o,enableGutterUtility:D,enableLineSelection:se,onLineSelectionEnd:w},t[32]=w,t[33]=o,t[34]=se,t[35]=D,t[36]=k):k=t[36];let A;t[37]===l?A=t[38]:(A=e=>e.type===`diff`?l(e.fileDiff,e.id,e.collapsed===!0):null,t[37]=l,t[38]=A);let j;t[39]!==b||t[40]!==S?(j=e=>(0,L.jsx)(`div`,{className:`py-1`,children:e.metadata.entries.map(e=>(0,L.jsx)(He,{kind:e.kind,rangeLabel:e.rangeLabel,text:e.text,onCancel:()=>b(e.id),onComment:t=>S(e.id,t),onDelete:()=>b(e.id)},e.id))}),t[39]=b,t[40]=S,t[41]=j):j=t[41];let M;return t[42]!==ae||t[43]!==f||t[44]!==k||t[45]!==A||t[46]!==j||t[47]!==T||t[48]!==E?(M=(0,L.jsx)(O,{...T,...E,items:ae,selectedLines:f,onSelectedLinesChange:p,options:k,renderHeaderPrefix:A,renderAnnotation:j}),t[42]=ae,t[43]=f,t[44]=k,t[45]=A,t[46]=j,t[47]=T,t[48]=E,t[49]=M):M=t[49],M}function z(e){return e.metadata.entries.map(Xe)}function Xe(e){return`${e.id}:${e.rangeLabel}:${e.text}`}function Ze(e){return[e.fileKey,e]}function B(e){return e.removeReviewComment}function Qe(e){return e.addReviewComment}function $e(e){return{diffPreview:w(e,{label:`environment-data:review:diff-preview`,tag:a.reviewGetDiffPreview,staleTimeMs:5e3})}}var et=$e(c);function V(e){return e.remoteName&&e.name.startsWith(`${e.remoteName}/`)?e.name.slice(e.remoteName.length+1):e.name}function tt(e,t){let n=new Set(t),r=e.map(e=>{let r=t.filter(t=>n.has(t)&&V(t)===e.name),i=r.find(e=>e.remoteName===`origin`)??r[0]??null;return i&&n.delete(i),{id:`local:${e.name}`,label:e.name,local:e,remote:i}}),i=t.filter(e=>n.has(e)).map(e=>({id:`remote:${e.name}`,label:e.name,local:null,remote:e}));return[...r,...i]}function nt(e,t){let n=t.trim().toLocaleLowerCase();return n.length===0?e:e.filter(e=>e.label.toLocaleLowerCase().includes(n)||e.local?.name.toLocaleLowerCase().includes(n)===!0||e.remote?.name.toLocaleLowerCase().includes(n)===!0)}var H=`__automatic_base_ref__`,rt=new Set,it=`
|
|
2
|
+
[data-diffs-header],
|
|
3
|
+
[data-diff],
|
|
4
|
+
[data-file],
|
|
5
|
+
[data-error-wrapper],
|
|
6
|
+
[data-virtualizer-buffer] {
|
|
7
|
+
--diffs-header-font-family: var(--font-sans) !important;
|
|
8
|
+
--diffs-font-family: var(--font-mono) !important;
|
|
9
|
+
--diffs-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
|
|
10
|
+
--diffs-light-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
|
|
11
|
+
--diffs-dark-bg: color-mix(in srgb, var(--card) 90%, var(--background)) !important;
|
|
12
|
+
--diffs-token-light-bg: transparent;
|
|
13
|
+
--diffs-token-dark-bg: transparent;
|
|
14
|
+
|
|
15
|
+
--diffs-bg-context-override: color-mix(in srgb, var(--background) 97%, var(--foreground));
|
|
16
|
+
--diffs-bg-hover-override: color-mix(in srgb, var(--background) 94%, var(--foreground));
|
|
17
|
+
--diffs-bg-separator-override: color-mix(in srgb, var(--background) 95%, var(--foreground));
|
|
18
|
+
--diffs-bg-buffer-override: color-mix(in srgb, var(--background) 90%, var(--foreground));
|
|
19
|
+
|
|
20
|
+
--diffs-bg-addition-override: color-mix(in srgb, var(--background) 92%, var(--success));
|
|
21
|
+
--diffs-bg-addition-number-override: color-mix(in srgb, var(--background) 88%, var(--success));
|
|
22
|
+
--diffs-bg-addition-hover-override: color-mix(in srgb, var(--background) 85%, var(--success));
|
|
23
|
+
--diffs-bg-addition-emphasis-override: color-mix(in srgb, var(--background) 80%, var(--success));
|
|
24
|
+
|
|
25
|
+
--diffs-bg-deletion-override: color-mix(in srgb, var(--background) 92%, var(--destructive));
|
|
26
|
+
--diffs-bg-deletion-number-override: color-mix(in srgb, var(--background) 88%, var(--destructive));
|
|
27
|
+
--diffs-bg-deletion-hover-override: color-mix(in srgb, var(--background) 85%, var(--destructive));
|
|
28
|
+
--diffs-bg-deletion-emphasis-override: color-mix(
|
|
29
|
+
in srgb,
|
|
30
|
+
var(--background) 80%,
|
|
31
|
+
var(--destructive)
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
background-color: var(--diffs-bg) !important;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
[data-file-info] {
|
|
38
|
+
background-color: color-mix(in srgb, var(--card) 94%, var(--foreground)) !important;
|
|
39
|
+
border-block-color: var(--border) !important;
|
|
40
|
+
color: var(--foreground) !important;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
[data-diffs-header] {
|
|
44
|
+
position: sticky !important;
|
|
45
|
+
top: 0;
|
|
46
|
+
z-index: 4;
|
|
47
|
+
background-color: color-mix(in srgb, var(--card) 94%, var(--foreground)) !important;
|
|
48
|
+
border-bottom: 1px solid var(--border) !important;
|
|
49
|
+
align-items: center !important;
|
|
50
|
+
font-family: var(--font-sans) !important;
|
|
51
|
+
font-size: 12px !important;
|
|
52
|
+
line-height: 1 !important;
|
|
53
|
+
min-height: 32px !important;
|
|
54
|
+
padding-block: 6px !important;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
[data-diffs-header] [data-header-content] {
|
|
58
|
+
align-items: center !important;
|
|
59
|
+
line-height: 1 !important;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
[data-diffs-header] [data-metadata] {
|
|
63
|
+
align-items: center !important;
|
|
64
|
+
line-height: 1 !important;
|
|
65
|
+
font-variant-numeric: tabular-nums;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
[data-diffs-header] [data-additions-count],
|
|
69
|
+
[data-diffs-header] [data-deletions-count] {
|
|
70
|
+
font-family: var(--font-mono) !important;
|
|
71
|
+
font-size: 11px !important;
|
|
72
|
+
font-variant-numeric: tabular-nums;
|
|
73
|
+
line-height: 1 !important;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
[data-diffs-header] [data-change-icon],
|
|
77
|
+
[data-diffs-header] [data-rename-icon] {
|
|
78
|
+
display: block;
|
|
79
|
+
flex-shrink: 0;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
[data-title] {
|
|
83
|
+
cursor: pointer;
|
|
84
|
+
transition:
|
|
85
|
+
color 120ms ease,
|
|
86
|
+
text-decoration-color 120ms ease;
|
|
87
|
+
text-decoration: underline;
|
|
88
|
+
text-decoration-color: transparent;
|
|
89
|
+
text-underline-offset: 2px;
|
|
90
|
+
font-family: var(--font-sans) !important;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
[data-title]:hover {
|
|
94
|
+
color: color-mix(in srgb, var(--foreground) 84%, var(--primary)) !important;
|
|
95
|
+
text-decoration-color: currentColor;
|
|
96
|
+
}
|
|
97
|
+
`;function U({mode:e=`inline`,composerDraftTarget:t,initialGitScope:n,threadRef:r}){let{resolvedTheme:a}=v(),c=de(),[ne]=(0,F.useState)(n),[re,m]=(0,F.useState)(`stacked`),[y,S]=(0,F.useState)(c.wordWrap),[w,T]=(0,F.useState)(c.diffIgnoreWhitespace),[O,ve]=(0,F.useState)(``),[Se,ze]=(0,F.useState)(()=>({scopeKey:null,fileKeys:rt})),He=(0,F.useRef)(null),Ue=r.threadId,I=he(r),qe=I?.projectId??null,Je=me(I&&qe?{environmentId:I.environmentId,projectId:qe}:null),R=I?.worktreePath??Je?.workspaceRoot,z=u(oe.configValueAtom(I?.environmentId??null)),Xe=Fe(I?.environmentId??null,z?.availableEditors??[]),Ze=l(I!=null&&R!=null?De.status({environmentId:I.environmentId,input:{cwd:R}}):null),B=N(e=>Ee(e.byThreadKey,r,ne===`unstaged`)),Qe=Ze.data?.isRepo??!0,{turnDiffSummaries:$e,inferredCheckpointTurnCountByTurnId:V}=ue(I),U=(0,F.useMemo)(()=>[...$e].toSorted((e,t)=>{let n=e.checkpointTurnCount??V[e.turnId]??0,r=t.checkpointTurnCount??V[t.turnId]??0;return n===r?t.completedAt.localeCompare(e.completedAt):r-n}),[V,$e]);(0,F.useEffect)(()=>{B.kind===`turn`&&N.getState().reconcileTurnSelection(r,U.map(e=>e.turnId))},[B,U,r]);let W=B.kind===`turn`?B.turnId:null,G=B.kind===`unstaged`?`unstaged`:`branch`,K=B.kind===`branch`?B.baseRef:null,at=B.kind===`turn`?B.filePath:null,ot=B.kind===`turn`?B.revealRequestId:0,q=W===null?void 0:U.find(e=>e.turnId===W)??U[0],J=q&&(q.checkpointTurnCount??V[q.turnId]),st=U[0],ct=W===null?G===`unstaged`?`Working tree`:`Branch changes`:q?.turnId===st?.turnId?`Latest turn`:`Turn ${J??`?`}`,lt=q?`turn:${q.turnId}`:G,Y=`${r.environmentId}:${r.threadId}:${lt}`,ut=Se.scopeKey===Y?Se.fileKeys:rt,dt=q?`Turn ${J??`?`}`:G===`unstaged`?`Working tree`:`Branch changes`,ft=(0,F.useMemo)(()=>typeof J==`number`?{fromTurnCount:Math.max(0,J-1),toTurnCount:J}:null,[J]),pt=Ke({environmentId:I?.environmentId??null,threadId:Ue,fromTurnCount:ft?.fromTurnCount??null,toTurnCount:ft?.toTurnCount??null,ignoreWhitespace:w,cacheScope:q?`turn:${q.turnId}`:null},{enabled:Qe&&q!==void 0}),mt=l(W===null&&I&&R?et.diffPreview({environmentId:I.environmentId,input:{cwd:R,...K?{baseRef:K}:{},ignoreWhitespace:w}}):null),ht=W===null&&mt.error?.includes(`configured workspace root`)===!0&&z?.cwd!==void 0&&z.cwd!==R,gt=l(ht&&I&&z?et.diffPreview({environmentId:I.environmentId,input:{cwd:z.cwd,...K?{baseRef:K}:{},ignoreWhitespace:w}}):null),X=ht?gt:mt,Z=X.data?.sources.find(e=>e.kind===(G===`unstaged`?`working-tree`:`branch-range`)),_t=l(W===null&&G===`branch`&&I&&X.data?.cwd?De.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`local`,...O.trim().length>0?{query:O.trim()}:{},limit:100}}):null),vt=l(W===null&&G===`branch`&&I&&X.data?.cwd?De.listRefs({environmentId:I.environmentId,input:{cwd:X.data.cwd,includeMatchingRemoteRefs:!0,refKind:`remote`,...O.trim().length>0?{query:O.trim()}:{},limit:100}}):null),yt=tt(_t.data?.refs.filter(e=>e.name!==Z?.headRef)??[],vt.data?.refs??[]),bt=nt(yt,O),xt=e=>K&&K===e.remote?.name?K:e.local?.name??e.remote?.name??e.id,St=[H,...yt.map(xt)],Ct=[...O.trim().length===0?[H]:[],...bt.map(xt)],wt=Z?.diff,Tt=q?pt.data?.diff:wt,Et=!q&&Z?.truncated===!0,Dt=q?pt.isPending:X.isPending,Ot=q?pt.error:X.error,kt=typeof Tt==`string`&&Tt.trim().length===0,Q=(0,F.useMemo)(()=>Be(Tt,`diff-panel:${a}`,{compactPartialHunkOffsets:W===null}),[a,Tt,W]),At=(0,F.useMemo)(()=>!Q||Q.kind!==`files`?[]:Q.files.toSorted((e,t)=>P(e).localeCompare(P(t),void 0,{numeric:!0,sensitivity:`base`})),[Q]),$=(0,F.useMemo)(()=>At.map(e=>{let t=Pe(e);return{fileDiff:e,filePath:P(e),fileKey:t,collapsed:ut.has(t)}}),[ut,At]),jt=(0,F.useMemo)(()=>$.map(e=>e.fileKey),[$]),Mt=M(jt,ut),Nt=(0,F.useMemo)(()=>Ae(At),[At]);(0,F.useEffect)(()=>{if(!at)return;let e=$.find(e=>e.filePath===at);e&&He.current?.scrollTo({type:`item`,id:e.fileKey,align:`start`})},[$,at,ot]);let Pt=Oe({threadRef:r,workspaceRoot:R??null}),Ft=(0,F.useCallback)(e=>{Ge({threadRef:r,filePath:e,activeCwd:R,openFileSurface:Pt,openInEditor:e=>{(async()=>{let t=await Xe(e);t._tag===`Failure`&&!C(t)&&console.warn(`Failed to open diff file in editor.`,{operation:`open-diff-file`,environmentId:r.environmentId,threadId:r.threadId,...ee(ae(t))})})()}})},[R,Pt,Xe,r]),It=(0,F.useCallback)(e=>{ze(t=>{let n=new Set(t.scopeKey===Y?t.fileKeys:[]);return n.has(e)?n.delete(e):n.add(e),{scopeKey:Y,fileKeys:n}})},[Y]),Lt=(0,F.useCallback)(()=>{ze(e=>{let t=e.scopeKey===Y?e.fileKeys:rt;return{scopeKey:Y,fileKeys:k(jt,t)}})},[Y,jt]),Rt=e=>{N.getState().selectTurn(r,e)},zt=e=>{N.getState().selectGitScope(r,e)},Bt=e=>{N.getState().selectBranchBaseRef(r,e)};return(0,L.jsx)(_e,{mode:e,header:(0,L.jsxs)(L.Fragment,{children:[(0,L.jsxs)(`div`,{className:`flex min-w-0 flex-1 items-center gap-3 [-webkit-app-region:no-drag]`,children:[(0,L.jsxs)(o,{children:[(0,L.jsxs)(i,{className:`inline-flex h-6 max-w-full items-center gap-1 rounded-md bg-muted/70 px-2 text-xs font-medium text-foreground outline-none transition-colors hover:bg-muted focus-visible:ring-2 focus-visible:ring-ring`,"aria-label":`Diff scope: ${ct}`,children:[(0,L.jsx)(`span`,{className:`truncate`,children:ct}),(0,L.jsx)(p,{className:`size-3.5 shrink-0 text-muted-foreground`})]}),(0,L.jsxs)(te,{align:`start`,className:`w-60`,children:[(0,L.jsx)(h,{className:W===null&&G===`unstaged`?`bg-foreground/[0.08]`:void 0,onClick:()=>zt(`unstaged`),children:(0,L.jsx)(`span`,{children:`Working tree`})}),(0,L.jsx)(h,{className:W===null&&G===`branch`?`bg-foreground/[0.08]`:void 0,onClick:()=>zt(`branch`),children:(0,L.jsx)(`span`,{children:`Branch changes`})}),(0,L.jsx)(h,{className:W!==null&&q?.turnId===st?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>{st&&Rt(st.turnId)},children:(0,L.jsx)(`span`,{children:`Latest turn`})}),(0,L.jsxs)(ie,{children:[(0,L.jsx)(f,{children:`Turn`}),(0,L.jsx)(g,{className:`w-64`,children:U.map(e=>{let t=e.checkpointTurnCount??V[e.turnId]??`?`;return(0,L.jsxs)(h,{className:e.turnId===q?.turnId?`bg-foreground/[0.08]`:void 0,onClick:()=>Rt(e.turnId),children:[(0,L.jsxs)(`span`,{children:[`Turn `,t]}),(0,L.jsx)(`span`,{className:`ml-auto text-xs tabular-nums text-muted-foreground`,children:Ve(e.completedAt,c.timestampFormat)})]},e.turnId)})})]})]})]}),W===null&&G===`branch`&&Z?.baseRef&&(0,L.jsxs)(`div`,{className:`flex min-w-0 max-w-full items-center gap-2 overflow-hidden text-xs text-muted-foreground`,title:`${Z.headRef??`HEAD`} → ${Z.baseRef}`,"aria-label":`Comparing ${Z.headRef??`HEAD`} against ${Z.baseRef}`,children:[(0,L.jsx)(`span`,{className:`min-w-0 max-w-48 truncate`,children:Z.headRef??`HEAD`}),(0,L.jsx)(Le,{className:`size-3.5 shrink-0 opacity-70`}),(0,L.jsxs)(je,{items:St,filteredItems:Ct,value:K??H,onOpenChange:e=>{e||ve(``)},onValueChange:e=>{e&&Bt(e===H?null:e)},children:[(0,L.jsxs)(be,{className:`inline-flex min-w-0 max-w-48 items-center gap-1 overflow-hidden rounded-md px-1.5 py-1 outline-none transition-colors hover:bg-muted hover:text-foreground focus-visible:ring-2 focus-visible:ring-ring`,"aria-label":`Change comparison target. Currently ${Z.baseRef}`,children:[(0,L.jsx)(`span`,{className:`min-w-0 truncate`,children:Z.baseRef}),(0,L.jsx)(p,{className:`size-3.5 shrink-0 opacity-70`})]}),(0,L.jsxs)(Re,{align:`start`,className:`w-72 min-w-0 max-w-[calc(100vw-1rem)] overflow-hidden [&>[data-slot=combobox-popup]]:min-w-0 [&>[data-slot=combobox-popup]]:overflow-hidden`,children:[(0,L.jsx)(`div`,{className:`min-w-0 shrink-0 px-3 pt-2.5`,children:(0,L.jsxs)(`div`,{className:`relative -translate-y-px border-b border-border/70 pb-1.5 transition-colors focus-within:border-ring`,children:[(0,L.jsx)(ge,{"aria-hidden":`true`,className:`pointer-events-none absolute top-1.5 left-0 size-4 shrink-0 text-muted-foreground/55`}),(0,L.jsx)(Te,{className:`[&_input]:h-6.5 [&_input]:ps-5 [&_input]:font-sans [&_input]:leading-6.5`,inputClassName:`rounded-none bg-transparent text-sm`,placeholder:`Search refs...`,showTrigger:!1,size:`sm`,unstyled:!0,value:O,onChange:e=>ve(e.target.value)})]})}),(0,L.jsxs)(`div`,{className:`grid shrink-0 grid-cols-[1rem_minmax(0,1fr)] items-center gap-2 border-b border-border/70 ps-3 pe-6.5 pt-2 pb-1.5 font-medium text-[10px] text-muted-foreground uppercase tracking-wide`,children:[(0,L.jsx)(`span`,{"aria-hidden":`true`}),(0,L.jsxs)(`div`,{className:`grid min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center`,children:[(0,L.jsx)(`span`,{children:`Branch`}),(0,L.jsx)(`span`,{className:`text-right`,children:`Remote`})]})]}),(0,L.jsx)(Ie,{children:`No matching refs.`}),(0,L.jsxs)(Ne,{className:`max-h-64 min-w-0 overflow-x-hidden`,children:[(0,L.jsx)(ye,{className:`h-8 w-full min-w-0 grid-cols-[1rem_minmax(0,1fr)] py-0`,contentClassName:`w-full min-w-0 overflow-hidden`,value:H,children:(0,L.jsx)(`span`,{className:`block min-w-0 truncate`,children:`Automatic`})}),yt.map(e=>{let t=xt(e),n=e.local!==null&&e.remote!==null,r=e.remote?.name===t;return(0,L.jsx)(ye,{className:`h-8 w-full min-w-0 grid-cols-[1rem_minmax(0,1fr)] py-0`,contentClassName:`w-full min-w-0 overflow-hidden`,value:t,children:(0,L.jsxs)(`div`,{className:`grid w-full min-w-0 grid-cols-[minmax(0,1fr)_2rem] items-center overflow-hidden`,children:[(0,L.jsx)(`span`,{className:`block min-w-0 truncate pe-2`,children:e.label}),n?(0,L.jsx)(`div`,{className:`flex justify-end`,onClick:e=>e.stopPropagation(),onPointerDown:e=>e.stopPropagation(),children:(0,L.jsx)(ke,{"aria-label":`Use remote version of ${e.label}`,checked:r,className:`[--thumb-size:--spacing(3)]`,onCheckedChange:t=>{let n=t?e.remote?.name:e.local?.name;n&&Bt(n)}})}):e.remote?(0,L.jsx)(`span`,{className:`flex justify-end text-muted-foreground`,title:`Remote only`,children:(0,L.jsx)(s,{"aria-hidden":`true`,className:`size-3`})}):null]})},e.id)})]})]})]})]})]}),(0,L.jsxs)(`div`,{className:`flex shrink-0 items-center gap-1 [-webkit-app-region:no-drag]`,children:[$.length>0&&(0,L.jsx)(we,{additions:Nt.additions,deletions:Nt.deletions,className:`mr-1 text-[11px]`,layout:`inline`}),$.length>0&&(0,L.jsxs)(x,{children:[(0,L.jsx)(D,{render:(0,L.jsx)(d,{type:`button`,size:`icon-xs`,variant:`outline`,"aria-label":Mt?`Expand all files`:`Collapse all files`,onClick:Lt}),children:Mt?(0,L.jsx)(Me,{className:`size-3`}):(0,L.jsx)(se,{className:`size-3`})}),(0,L.jsx)(_,{side:`top`,children:Mt?`Expand all files`:`Collapse all files`})]}),(0,L.jsxs)(A,{className:`shrink-0`,variant:`outline`,size:`xs`,value:[re],onValueChange:e=>{let t=e[0];(t===`stacked`||t===`split`)&&m(t)},children:[(0,L.jsx)(le,{"aria-label":`Stacked diff view`,value:`stacked`,children:(0,L.jsx)(j,{className:`size-3`})}),(0,L.jsx)(le,{"aria-label":`Split diff view`,value:`split`,children:(0,L.jsx)(ce,{className:`size-3`})})]}),(0,L.jsxs)(x,{children:[(0,L.jsx)(D,{render:(0,L.jsx)(le,{"aria-label":y?`Disable diff line wrapping`:`Enable diff line wrapping`,variant:`outline`,size:`xs`,pressed:y,onPressedChange:e=>{S(!!e)}}),children:(0,L.jsx)(pe,{className:`size-3`})}),(0,L.jsx)(_,{side:`top`,children:y?`Disable line wrapping`:`Enable line wrapping`})]}),(0,L.jsxs)(x,{children:[(0,L.jsx)(D,{render:(0,L.jsx)(le,{"aria-label":w?`Show whitespace changes`:`Hide whitespace changes`,variant:`outline`,size:`xs`,pressed:w,onPressedChange:e=>{T(!!e)}}),children:(0,L.jsx)(We,{className:`size-3`})}),(0,L.jsx)(_,{side:`top`,children:w?`Show whitespace changes`:`Hide whitespace changes`})]})]})]}),children:I?Qe?W!==null&&U.length===0?(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`No completed turns yet.`}):(0,L.jsx)(L.Fragment,{children:(0,L.jsxs)(`div`,{className:`diff-panel-viewport flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden`,children:[Et&&(0,L.jsx)(`p`,{className:`shrink-0 border-b border-border/70 bg-muted/40 px-3 py-1.5 text-[11px] text-muted-foreground`,children:`This diff was truncated because it exceeded the preview limit. The changes shown are incomplete.`}),Ot&&!Q&&(0,L.jsx)(`div`,{className:`px-3`,children:(0,L.jsx)(`p`,{className:`mb-2 text-[11px] text-red-500/80`,children:Ot})}),Q?Q.kind===`files`?(0,L.jsx)(`div`,{className:`min-h-0 flex-1`,onClickCapture:e=>{let t=(e.nativeEvent.composedPath?.()??[]).find(e=>e instanceof HTMLElement&&e.hasAttribute(`data-title`))?.textContent?.trim();t&&Ft(t)},children:(0,L.jsx)(Ye,{viewerRef:He,className:`diff-render-surface h-full min-h-0 overflow-auto`,files:$,sectionId:lt,sectionTitle:dt,composerDraftTarget:t,renderHeaderPrefix:(e,t,n)=>{let r=P(e);return(0,L.jsxs)(x,{children:[(0,L.jsx)(D,{render:(0,L.jsx)(`button`,{type:`button`,className:b(`inline-flex size-5 shrink-0 cursor-pointer items-center justify-center rounded-sm border-0 bg-transparent p-0 transition-colors hover:bg-foreground/10 focus-visible:outline-hidden`,xe(e)),"aria-label":n?`Expand ${r}`:`Collapse ${r}`,"aria-expanded":!n,onClick:e=>{e.stopPropagation(),It(t)}}),children:n?(0,L.jsx)(E,{className:`size-4`}):(0,L.jsx)(p,{className:`size-4`})}),(0,L.jsx)(_,{side:`top`,children:n?`Expand diff`:`Collapse diff`})]})},options:{diffStyle:re===`split`?`split`:`unified`,lineDiffType:`none`,overflow:y?`wrap`:`scroll`,theme:Ce(a),themeType:a,unsafeCSS:it,stickyHeaders:!0,itemMetrics:{diffHeaderHeight:33},layout:{paddingTop:0,paddingBottom:8,gap:8}}},Y??lt)}):(0,L.jsx)(`div`,{className:`min-h-0 flex-1 overflow-auto p-2`,children:(0,L.jsxs)(`div`,{className:`space-y-2`,children:[(0,L.jsx)(`p`,{className:`text-[11px] text-muted-foreground/75`,children:Q.reason}),(0,L.jsx)(`pre`,{className:b(`max-h-[72vh] rounded-md border border-border/70 bg-background/70 p-3 font-mono text-[11px] leading-relaxed text-muted-foreground/90`,y?`overflow-auto whitespace-pre-wrap wrap-break-word`:`overflow-auto`),children:Q.text})]})}):Dt?(0,L.jsx)(fe,{label:q?`Loading checkpoint diff...`:G===`unstaged`?`Loading working tree diff...`:`Loading branch diff...`}):(0,L.jsx)(`div`,{className:`flex h-full items-center justify-center px-3 py-2 text-xs text-muted-foreground/70`,children:(0,L.jsx)(`p`,{children:kt?`No net changes in this selection.`:`No patch available for this selection.`})})]})}):(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`Turn diffs are unavailable because this project is not a git repository.`}):(0,L.jsx)(`div`,{className:`flex flex-1 items-center justify-center px-5 text-center text-xs text-muted-foreground/70`,children:`Select a thread to inspect turn diffs.`})})}export{ve as DiffWorkerPoolProvider,U as default};
|
|
98
|
+
//# sourceMappingURL=DiffPanel-D-49iCgp.js.map
|