@p4code/cli 0.5.3 → 0.5.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -260,7 +260,7 @@ const make$115 = () => {
260
260
  const layer$118 = Layer.sync(NetService, make$115);
261
261
  //#endregion
262
262
  //#region package.json
263
- var version$1 = "0.5.3";
263
+ var version$1 = "0.5.4";
264
264
  //#endregion
265
265
  //#region src/config.ts
266
266
  /**
@@ -9806,6 +9806,7 @@ const FusionModelPair = Schema$1.Struct({
9806
9806
  supervisor: ModelSelection
9807
9807
  });
9808
9808
  const ClientSettingsSchema = Schema$1.Struct({
9809
+ fusionHiddenSuggestionKeys: Schema$1.Array(Schema$1.String).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
9809
9810
  fusionPairOrder: Schema$1.Record(Schema$1.String, Schema$1.Array(Schema$1.String)).pipe(Schema$1.withDecodingDefault(Effect.succeed({}))),
9810
9811
  fusionRecentPairs: Schema$1.Array(FusionModelPair).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
9811
9812
  fusionFavoritePairs: Schema$1.Array(FusionModelPair).pipe(Schema$1.withDecodingDefault(Effect.succeed([]))),
@@ -10399,6 +10400,7 @@ const ServerSettingsPatch = Schema$1.Struct({
10399
10400
  providerInstances: Schema$1.optionalKey(Schema$1.Record(ProviderInstanceId, ProviderInstanceConfig))
10400
10401
  });
10401
10402
  Schema$1.Struct({
10403
+ fusionHiddenSuggestionKeys: Schema$1.optionalKey(Schema$1.Array(Schema$1.String)),
10402
10404
  fusionPairOrder: Schema$1.optionalKey(Schema$1.Record(Schema$1.String, Schema$1.Array(Schema$1.String))),
10403
10405
  fusionRecentPairs: Schema$1.optionalKey(Schema$1.Array(FusionModelPair)),
10404
10406
  fusionFavoritePairs: Schema$1.optionalKey(Schema$1.Array(FusionModelPair)),
@@ -11777,6 +11779,13 @@ const ThreadPairCreateResult = Schema$1.Struct({
11777
11779
  watcherThreadId: ThreadId,
11778
11780
  continuationMessageId: MessageId
11779
11781
  });
11782
+ const ThreadPairDetachInput = Schema$1.Struct({ pairId: ThreadPairId.annotate({ description: "The active Fusion pair to detach. This session must be its implementer and must have created its watcher with thread_spawn." }) });
11783
+ const ThreadPairDetachResult = Schema$1.Struct({
11784
+ pairId: ThreadPairId,
11785
+ implementerThreadId: ThreadId,
11786
+ watcherThreadId: ThreadId,
11787
+ detachedAt: IsoDateTime
11788
+ });
11780
11789
  const ThreadConfigureInput = Schema$1.Struct({
11781
11790
  threadId: ControlTargetThreadId,
11782
11791
  title: Schema$1.optional(TrimmedNonEmptyString),
@@ -13335,6 +13344,30 @@ var ProviderSetupError = class extends Schema$1.TaggedErrorClass()("ProviderSetu
13335
13344
  }
13336
13345
  };
13337
13346
  //#endregion
13347
+ //#region ../../packages/contracts/src/deviceCommand.ts
13348
+ const MAX_COORDINATE = 32768;
13349
+ const MAX_TEXT_LENGTH = 4096;
13350
+ const target = {
13351
+ hostId: DeviceHostId,
13352
+ deviceId: DeviceId
13353
+ };
13354
+ const Coordinate = Schema$1.Int.check(Schema$1.isBetween({
13355
+ minimum: 0,
13356
+ maximum: MAX_COORDINATE
13357
+ }));
13358
+ /** Deliberately excludes arbitrary commands, flags, paths and daemon configuration. */
13359
+ const DeviceCommandInput = Schema$1.Union([Schema$1.Struct({
13360
+ ...target,
13361
+ command: Schema$1.Literal("press"),
13362
+ x: Coordinate,
13363
+ y: Coordinate
13364
+ }), Schema$1.Struct({
13365
+ ...target,
13366
+ command: Schema$1.Literal("type"),
13367
+ text: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(MAX_TEXT_LENGTH))
13368
+ })]);
13369
+ const DeviceCommandResult = Schema$1.Struct({ ok: Schema$1.Literal(true) });
13370
+ //#endregion
13338
13371
  //#region ../../packages/contracts/src/computerUse.ts
13339
13372
  const COMPUTER_USE_MAX_CODE_CHARS = 1e5;
13340
13373
  const COMPUTER_USE_MAX_TIMEOUT_MS = 6e4;
@@ -13374,9 +13407,36 @@ const ComputerUseJsInput = Schema$1.Struct({
13374
13407
  title: Schema$1.optional(Schema$1.String.check(Schema$1.isMaxLength(COMPUTER_USE_MAX_TITLE_CHARS))),
13375
13408
  timeout_ms: Schema$1.optional(Schema$1.Int.check(Schema$1.isGreaterThan(0), Schema$1.isLessThanOrEqualTo(COMPUTER_USE_MAX_TIMEOUT_MS)))
13376
13409
  });
13410
+ const COMPUTER_USE_PREVIEW_MAX_IMAGE_CHARS = 5e5;
13411
+ const ComputerUseLogicalSize = Schema$1.Struct({
13412
+ width: Schema$1.Number.check(Schema$1.isGreaterThan(0)),
13413
+ height: Schema$1.Number.check(Schema$1.isGreaterThan(0))
13414
+ });
13415
+ const ComputerUsePreviewFrame = Schema$1.Struct({
13416
+ appName: Schema$1.String,
13417
+ windowId: Schema$1.String,
13418
+ sequence: Schema$1.Int,
13419
+ image: Schema$1.optional(Schema$1.Struct({
13420
+ mimeType: Schema$1.Literal("image/jpeg"),
13421
+ data: Schema$1.String.check(Schema$1.isMaxLength(COMPUTER_USE_PREVIEW_MAX_IMAGE_CHARS))
13422
+ })),
13423
+ logicalSize: Schema$1.optional(ComputerUseLogicalSize),
13424
+ pointer: Schema$1.optional(Schema$1.Struct({
13425
+ x: Schema$1.Number,
13426
+ y: Schema$1.Number,
13427
+ sequence: Schema$1.Int
13428
+ })),
13429
+ error: Schema$1.optional(Schema$1.String)
13430
+ });
13431
+ const ComputerUsePreview = Schema$1.Struct({
13432
+ session: ComputerUseSession,
13433
+ host: ComputerUseHost,
13434
+ frame: ComputerUsePreviewFrame
13435
+ });
13377
13436
  const ComputerUseOutput = Schema$1.Struct({
13378
13437
  text: Schema$1.String.check(Schema$1.isMaxLength(COMPUTER_USE_MAX_OUTPUT_CHARS)),
13379
13438
  truncated: Schema$1.Boolean,
13439
+ preview: Schema$1.optional(ComputerUsePreviewFrame),
13380
13440
  images: Schema$1.optional(Schema$1.Array(Schema$1.Struct({
13381
13441
  mimeType: Schema$1.Literals(["image/png", "image/jpeg"]),
13382
13442
  data: Schema$1.String.check(Schema$1.isMaxLength(COMPUTER_USE_MAX_IMAGE_CHARS))
@@ -13392,7 +13452,8 @@ const ComputerUseHostRequest = Schema$1.Struct({
13392
13452
  "js_reset",
13393
13453
  "close",
13394
13454
  "stop",
13395
- "resume"
13455
+ "resume",
13456
+ "preview"
13396
13457
  ]),
13397
13458
  input: Schema$1.optional(ComputerUseJsInput)
13398
13459
  });
@@ -13439,6 +13500,26 @@ const ComputerUseHostResponse = Schema$1.Struct({
13439
13500
  error: ComputerUseError
13440
13501
  })])
13441
13502
  });
13503
+ const ComputerUseDeviceControl = Schema$1.Struct({
13504
+ hostId: DeviceHostId,
13505
+ deviceId: DeviceId,
13506
+ platform: DevicePlatform,
13507
+ leaseId: DeviceId,
13508
+ name: Schema$1.String,
13509
+ hostLabel: Schema$1.String,
13510
+ logicalSize: Schema$1.optional(ComputerUseLogicalSize),
13511
+ pointer: Schema$1.Struct({
13512
+ x: Schema$1.Number.check(Schema$1.isBetween({
13513
+ minimum: 0,
13514
+ maximum: 1
13515
+ })),
13516
+ y: Schema$1.Number.check(Schema$1.isBetween({
13517
+ minimum: 0,
13518
+ maximum: 1
13519
+ })),
13520
+ sequence: Schema$1.Int
13521
+ })
13522
+ });
13442
13523
  const ComputerUseHostReport = Schema$1.Struct({
13443
13524
  hostId: TrimmedNonEmptyString,
13444
13525
  connectionId: TrimmedNonEmptyString,
@@ -13447,7 +13528,9 @@ const ComputerUseHostReport = Schema$1.Struct({
13447
13528
  "active",
13448
13529
  "closed",
13449
13530
  "stopped"
13450
- ])
13531
+ ]),
13532
+ previewApp: Schema$1.optional(Schema$1.String),
13533
+ deviceControl: Schema$1.optional(Schema$1.NullOr(ComputerUseDeviceControl))
13451
13534
  });
13452
13535
  const ComputerUseControlState = Schema$1.Struct({
13453
13536
  session: ComputerUseSession,
@@ -13457,7 +13540,9 @@ const ComputerUseControlState = Schema$1.Struct({
13457
13540
  "stopping",
13458
13541
  "stopped",
13459
13542
  "stop-unconfirmed"
13460
- ])
13543
+ ]),
13544
+ previewApp: Schema$1.optional(Schema$1.String),
13545
+ deviceControl: Schema$1.optional(Schema$1.NullOr(ComputerUseDeviceControl))
13461
13546
  });
13462
13547
  const ComputerUseControlInput = Schema$1.Struct({
13463
13548
  threadId: ThreadId,
@@ -13480,6 +13565,51 @@ const ComputerUseSourceAttestation = Schema$1.Struct({
13480
13565
  connectionId: TrimmedNonEmptyString,
13481
13566
  expiresAt: Schema$1.Number
13482
13567
  });
13568
+ /** Device commands travel back to the environment through the live helper request lease. */
13569
+ const ComputerUseDeviceTarget = {
13570
+ hostId: DeviceHostId,
13571
+ deviceId: DeviceId,
13572
+ leaseId: DeviceId
13573
+ };
13574
+ const ComputerUseDeviceOperation = Schema$1.Union([
13575
+ Schema$1.Struct({ method: Schema$1.Literal("list") }),
13576
+ Schema$1.Struct({
13577
+ method: Schema$1.Literal("open"),
13578
+ hostId: DeviceHostId,
13579
+ deviceId: DeviceId,
13580
+ platform: DevicePlatform
13581
+ }),
13582
+ Schema$1.Struct({
13583
+ method: Schema$1.Literals([
13584
+ "state",
13585
+ "screenshot",
13586
+ "close"
13587
+ ]),
13588
+ ...ComputerUseDeviceTarget
13589
+ }),
13590
+ Schema$1.Struct({
13591
+ method: Schema$1.Literal("command"),
13592
+ leaseId: DeviceId,
13593
+ command: DeviceCommandInput
13594
+ })
13595
+ ]);
13596
+ const ComputerUseDeviceRequest = Schema$1.Struct({
13597
+ hostId: TrimmedNonEmptyString,
13598
+ connectionId: TrimmedNonEmptyString,
13599
+ requestId: TrimmedNonEmptyString,
13600
+ callId: TrimmedNonEmptyString,
13601
+ operation: ComputerUseDeviceOperation
13602
+ });
13603
+ Schema$1.Struct({
13604
+ callId: TrimmedNonEmptyString,
13605
+ result: Schema$1.Union([Schema$1.Struct({
13606
+ ok: Schema$1.Literal(true),
13607
+ value: Schema$1.Unknown
13608
+ }), Schema$1.Struct({
13609
+ ok: Schema$1.Literal(false),
13610
+ error: ComputerUseError
13611
+ })])
13612
+ });
13483
13613
  //#endregion
13484
13614
  //#region ../../packages/contracts/src/rpc.ts
13485
13615
  const WS_METHODS = {
@@ -13524,6 +13654,7 @@ const WS_METHODS = {
13524
13654
  computerUseList: "computerUse.list",
13525
13655
  computerUseControls: "computerUse.controls",
13526
13656
  computerUseControl: "computerUse.control",
13657
+ computerUsePreview: "computerUse.preview",
13527
13658
  computerUseRespond: "computerUse.respond",
13528
13659
  previewAutomationConnect: "previewAutomation.connect",
13529
13660
  previewAutomationRespond: "previewAutomation.respond",
@@ -14553,6 +14684,12 @@ const WsComputerUseControlsRpc = Rpc.make(WS_METHODS.computerUseControls, {
14553
14684
  error: EnvironmentAuthorizationError,
14554
14685
  stream: true
14555
14686
  });
14687
+ const WsComputerUsePreviewRpc = Rpc.make(WS_METHODS.computerUsePreview, {
14688
+ payload: ComputerUseSession,
14689
+ success: ComputerUsePreview,
14690
+ error: Schema$1.Union([ComputerUseError, EnvironmentAuthorizationError]),
14691
+ stream: true
14692
+ });
14556
14693
  const WsComputerUseControlRpc = Rpc.make(WS_METHODS.computerUseControl, {
14557
14694
  payload: ComputerUseControlInput,
14558
14695
  error: Schema$1.Union([ComputerUseError, EnvironmentAuthorizationError])
@@ -14663,31 +14800,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
14663
14800
  error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
14664
14801
  stream: true
14665
14802
  });
14666
- const WsRpcGroup = RpcGroup.make(WsDeviceGetStateRpc, WsDeviceListRpc, WsDeviceConfigureRpc, WsDeviceOpenRpc, WsDeviceCloseRpc, WsDeviceDetailRpc, WsDeviceActionRpc, WsSubscribeDevicesRpc, WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerProviderAuthStartRpc, WsServerProviderAuthCompleteRpc, WsServerProviderAuthCancelRpc, WsServerProviderAuthLogoutRpc, WsServerProviderAuthSubscribeRpc, WsServerProviderInstallStartRpc, WsServerProviderInstallCancelRpc, WsServerProviderInstallRemoveRpc, WsServerProviderInstallSubscribeRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetHostResourcesRpc, WsServerGetResourceTelemetryRpc, WsServerGetResourceTelemetryHistoryRpc, WsServerRetryResourceTelemetryRpc, WsSubscribeResourceTelemetryRpc, WsBtwAskRpc, WsBtwCancelRpc, WsServerGetUsageSummaryRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, WsPullRequestsStackRpc, WsPullRequestsActivityRpc, WsPullRequestsDiffFileContentsRpc, WsPullRequestsRunActionRpc, WsPullRequestsUpdateRpc, WsPullRequestsCommentRpc, WsPullRequestsUpdateCommentRpc, WsPullRequestsSubmitReviewRpc, WsPullRequestsReplyToThreadRpc, WsPullRequestsSetThreadResolutionRpc, WsPullRequestsSetReactionRpc, WsPullRequestsInvalidateRpc, WsPullRequestsReviewerCandidatesRpc, WsPullRequestsRequestReviewersRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchContentsRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsComputerUseConnectRpc, WsComputerUseListRpc, WsComputerUseControlsRpc, WsComputerUseControlRpc, WsComputerUseRespondRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsFeedListRpc, WsFeedRefreshRpc, WsFeedSourcesListRpc, WsFeedSourcesUpsertRpc, WsFeedSourcesDeleteRpc, WsFeedMarkReadRpc, WsFeedCleanupRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsSkillRegistrySearchRpc, WsSkillRegistryFetchRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsTrackerStatusRpc, WsTrackerSetApiKeyRpc, WsTrackerClearApiKeyRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetWorkflowScriptRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationSearchThreadsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
14667
- //#endregion
14668
- //#region ../../packages/contracts/src/deviceCommand.ts
14669
- const MAX_COORDINATE = 32768;
14670
- const MAX_TEXT_LENGTH = 4096;
14671
- const target = {
14672
- hostId: DeviceHostId,
14673
- deviceId: DeviceId
14674
- };
14675
- const Coordinate = Schema$1.Int.check(Schema$1.isBetween({
14676
- minimum: 0,
14677
- maximum: MAX_COORDINATE
14678
- }));
14679
- /** Deliberately excludes arbitrary commands, flags, paths and daemon configuration. */
14680
- const DeviceCommandInput = Schema$1.Union([Schema$1.Struct({
14681
- ...target,
14682
- command: Schema$1.Literal("press"),
14683
- x: Coordinate,
14684
- y: Coordinate
14685
- }), Schema$1.Struct({
14686
- ...target,
14687
- command: Schema$1.Literal("type"),
14688
- text: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(MAX_TEXT_LENGTH))
14689
- })]);
14690
- const DeviceCommandResult = Schema$1.Struct({ ok: Schema$1.Literal(true) });
14803
+ const WsRpcGroup = RpcGroup.make(WsDeviceGetStateRpc, WsDeviceListRpc, WsDeviceConfigureRpc, WsDeviceOpenRpc, WsDeviceCloseRpc, WsDeviceDetailRpc, WsDeviceActionRpc, WsSubscribeDevicesRpc, WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerProviderAuthStartRpc, WsServerProviderAuthCompleteRpc, WsServerProviderAuthCancelRpc, WsServerProviderAuthLogoutRpc, WsServerProviderAuthSubscribeRpc, WsServerProviderInstallStartRpc, WsServerProviderInstallCancelRpc, WsServerProviderInstallRemoveRpc, WsServerProviderInstallSubscribeRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsServerGetHostResourcesRpc, WsServerGetResourceTelemetryRpc, WsServerGetResourceTelemetryHistoryRpc, WsServerRetryResourceTelemetryRpc, WsSubscribeResourceTelemetryRpc, WsBtwAskRpc, WsBtwCancelRpc, WsServerGetUsageSummaryRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, WsPullRequestsStackRpc, WsPullRequestsActivityRpc, WsPullRequestsDiffFileContentsRpc, WsPullRequestsRunActionRpc, WsPullRequestsUpdateRpc, WsPullRequestsCommentRpc, WsPullRequestsUpdateCommentRpc, WsPullRequestsSubmitReviewRpc, WsPullRequestsReplyToThreadRpc, WsPullRequestsSetThreadResolutionRpc, WsPullRequestsSetReactionRpc, WsPullRequestsInvalidateRpc, WsPullRequestsReviewerCandidatesRpc, WsPullRequestsRequestReviewersRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, WsProjectsSearchContentsRpc, WsProjectsSearchEntriesRpc, WsProjectsWriteFileRpc, WsShellOpenInEditorRpc, WsFilesystemBrowseRpc, WsAssetsCreateUrlRpc, WsSubscribeVcsStatusRpc, WsVcsPullRpc, WsVcsRefreshStatusRpc, WsGitRunStackedActionRpc, WsGitResolvePullRequestRpc, WsGitPreparePullRequestThreadRpc, WsVcsListRefsRpc, WsVcsCreateWorktreeRpc, WsVcsRemoveWorktreeRpc, WsVcsCreateRefRpc, WsVcsSwitchRefRpc, WsVcsInitRpc, WsReviewGetDiffPreviewRpc, WsTerminalOpenRpc, WsTerminalAttachRpc, WsTerminalWriteRpc, WsTerminalResizeRpc, WsTerminalClearRpc, WsTerminalRestartRpc, WsTerminalCloseRpc, WsSubscribeTerminalEventsRpc, WsSubscribeTerminalMetadataRpc, WsPreviewOpenRpc, WsPreviewNavigateRpc, WsPreviewResizeRpc, WsPreviewRefreshRpc, WsPreviewCloseRpc, WsPreviewListRpc, WsPreviewReportStatusRpc, WsComputerUseConnectRpc, WsComputerUseListRpc, WsComputerUseControlsRpc, WsComputerUseControlRpc, WsComputerUsePreviewRpc, WsComputerUseRespondRpc, WsPreviewAutomationConnectRpc, WsPreviewAutomationRespondRpc, WsPreviewAutomationFocusHostRpc, WsSubscribePreviewEventsRpc, WsSubscribeDiscoveredLocalServersRpc, WsSubscribeServerConfigRpc, WsSubscribeServerLifecycleRpc, WsSubscribeAuthAccessRpc, WsTasksListRpc, WsTasksGetRpc, WsTasksCreateRpc, WsTasksUpdateRpc, WsTasksDeleteRpc, WsTasksStartThreadRpc, WsFeedListRpc, WsFeedRefreshRpc, WsFeedSourcesListRpc, WsFeedSourcesUpsertRpc, WsFeedSourcesDeleteRpc, WsFeedMarkReadRpc, WsFeedCleanupRpc, WsSubscribeTasksRpc, WsHubGetSyncStatusRpc, WsHubConnectRpc, WsHubDisconnectRpc, WsHubSetSyncModeRpc, WsHubSetShareModeRpc, WsHubMintTokenRpc, WsSkillsSyncRpc, WsSkillsPublishRpc, WsSkillsPublishAllRpc, WsSkillsUnpublishRpc, WsAssetsReadRpc, WsAssetsSaveRpc, WsAssetsDeleteRpc, WsAssetsCreateLocalRpc, WsAssetsRemoveLocalRpc, WsSkillRegistrySearchRpc, WsSkillRegistryFetchRpc, WsMcpListRpc, WsMcpSaveRpc, WsMcpRemoveRpc, WsMcpSetSecretRpc, WsMcpOAuthBeginRpc, WsMcpOAuthDisconnectRpc, WsTrackerStatusRpc, WsTrackerSetApiKeyRpc, WsTrackerClearApiKeyRpc, WsOrchestrationDispatchCommandRpc, WsOrchestrationGetTurnDiffRpc, WsOrchestrationGetWorkflowScriptRpc, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationSearchThreadsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
14691
14804
  //#endregion
14692
14805
  //#region ../../packages/shared/src/oauthScope.ts
14693
14806
  const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
@@ -20381,7 +20494,7 @@ function resolveFdPath(fd, platform) {
20381
20494
  const modeFlag = Flag.choice("mode", RuntimeMode$1.literals).pipe(Flag.withDescription("Runtime mode. `desktop` keeps loopback defaults unless overridden."), Flag.optional);
20382
20495
  const portFlag$1 = Flag.integer("port").pipe(Flag.withSchema(PortSchema), Flag.withDescription("Port for the HTTP/WebSocket server."), Flag.optional);
20383
20496
  const hostFlag$1 = Flag.string("host").pipe(Flag.withDescription("Host/interface to bind (for example 127.0.0.1, 0.0.0.0, or a Tailnet IP)."), Flag.optional);
20384
- const baseDirFlag$1 = Flag.string("base-dir").pipe(Flag.withDescription("Explicit P4Code data directory; runtime state is stored under userdata (equivalent to P4CODE_HOME)."), Flag.optional);
20497
+ const baseDirFlag$1 = Flag.string("base-dir").pipe(Flag.withDescription("Explicit P4 Code data directory; runtime state is stored under userdata (equivalent to P4CODE_HOME)."), Flag.optional);
20385
20498
  const devUrlFlag = Flag.string("dev-url").pipe(Flag.withSchema(Schema$1.URLFromString), Flag.withDescription("Dev web URL to proxy/redirect to (equivalent to VITE_DEV_SERVER_URL)."), Flag.optional);
20386
20499
  const noBrowserFlag = Flag.boolean("no-browser").pipe(Flag.withDescription("Disable automatic browser opening."), Flag.optional);
20387
20500
  const bootstrapFdFlag = Flag.integer("bootstrap-fd").pipe(Flag.withSchema(Schema$1.Int), Flag.withDescription("Read one-time bootstrap secrets from the given file descriptor."), Flag.optional);
@@ -21597,7 +21710,7 @@ const renderTerminalQrCode = (value, margin = 2) => {
21597
21710
  return rows.join("\n");
21598
21711
  };
21599
21712
  const formatHeadlessServeOutput = (accessInfo) => [
21600
- "P4Code server is ready.",
21713
+ "P4 Code server is ready.",
21601
21714
  `Connection string: ${accessInfo.connectionString}`,
21602
21715
  `Token: ${accessInfo.token}`,
21603
21716
  `Pairing URL: ${accessInfo.pairingUrl}`,
@@ -27810,7 +27923,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
27810
27923
  const config = yield* HubConfig;
27811
27924
  const address = (yield* HttpServer.HttpServer).address;
27812
27925
  const port = address._tag === "TcpAddress" ? address.port : config.port;
27813
- yield* Effect.log("P4Code hub listening", {
27926
+ yield* Effect.log("P4 Code hub listening", {
27814
27927
  host: config.host,
27815
27928
  port,
27816
27929
  dbPath: config.dbPath,
@@ -32627,7 +32740,7 @@ const resolveHubPaths = Effect.fn("resolveHubPaths")(function* (baseDirFlag) {
32627
32740
  tokensPath: path.join(hubDir, "tokens.json")
32628
32741
  };
32629
32742
  });
32630
- const baseDirFlag = Flag.string("base-dir").pipe(Flag.withDescription("Base directory for hub state. Defaults to the P4Code home directory."), Flag.optional);
32743
+ const baseDirFlag = Flag.string("base-dir").pipe(Flag.withDescription("Base directory for hub state. Defaults to the P4 Code home directory."), Flag.optional);
32631
32744
  const hostFlag = Flag.string("host").pipe(Flag.withDescription("Interface to bind. Defaults to 127.0.0.1; pass a Tailnet address to expose the hub to your other machines."), Flag.optional);
32632
32745
  const portFlag = Flag.integer("port").pipe(Flag.withDescription("Port for the hub HTTP server."), Flag.optional);
32633
32746
  const labelFlag = Flag.string("label").pipe(Flag.withDescription("Name of the server this token is for, for example `studio`."));
@@ -32635,7 +32748,7 @@ const serveHubCommand = Command.make("serve", {
32635
32748
  baseDir: baseDirFlag,
32636
32749
  host: hostFlag,
32637
32750
  port: portFlag
32638
- }).pipe(Command.withDescription("Run the P4Code hub: the shared task board for all of your servers."), Command.withHandler((flags) => Effect.gen(function* () {
32751
+ }).pipe(Command.withDescription("Run the P4 Code hub: the shared task board for all of your servers."), Command.withHandler((flags) => Effect.gen(function* () {
32639
32752
  const env = yield* HostProcessEnvironment;
32640
32753
  const paths = yield* resolveHubPaths(flags.baseDir);
32641
32754
  const tokenFile = yield* readHubTokenFile(paths.tokensPath);
@@ -32723,7 +32836,7 @@ const tokenCommand = Command.make("token", {}).pipe(Command.withDescription("Man
32723
32836
  listTokensCommand,
32724
32837
  revokeTokenCommand
32725
32838
  ]));
32726
- const hubCommand = Command.make("hub", {}).pipe(Command.withDescription("Run and manage the P4Code hub."), Command.withSubcommands([
32839
+ const hubCommand = Command.make("hub", {}).pipe(Command.withDescription("Run and manage the P4 Code hub."), Command.withSubcommands([
32727
32840
  serveHubCommand,
32728
32841
  tokenCommand,
32729
32842
  ...hubLinkCommands
@@ -43864,7 +43977,7 @@ function quoteSystemdValue(value) {
43864
43977
  function renderBootServiceUnit(plan) {
43865
43978
  return [
43866
43979
  "[Unit]",
43867
- "Description=P4Code server",
43980
+ "Description=P4 Code server",
43868
43981
  "StartLimitIntervalSec=300",
43869
43982
  "StartLimitBurst=5",
43870
43983
  "",
@@ -43971,7 +44084,7 @@ function formatCommandInvocation(command, args) {
43971
44084
  }
43972
44085
  var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootServiceInstallError", { cause: Schema$1.Defect() }) {
43973
44086
  get message() {
43974
- return "Could not set up the P4Code background service.";
44087
+ return "Could not set up the P4 Code background service.";
43975
44088
  }
43976
44089
  };
43977
44090
  var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
@@ -44328,7 +44441,7 @@ const make$89 = Effect.fn("cloud.server_self_update.make")(function* (options) {
44328
44441
  contents
44329
44442
  }).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path$1.Path, path));
44330
44443
  const update = Effect.fn("cloud.server_self_update.update")(function* (input) {
44331
- if (capability === "desktop-managed") return yield* failWith("This server is managed by the P4Code desktop app on its machine; update the desktop app to update it.");
44444
+ if (capability === "desktop-managed") return yield* failWith("This server is managed by the P4 Code desktop app on its machine; update the desktop app to update it.");
44332
44445
  if (capability === null) return yield* failWith("This server cannot update itself; relaunch it manually with the new version.");
44333
44446
  const activeMethod = capability;
44334
44447
  const targetVersion = input.targetVersion.trim();
@@ -44944,6 +45057,7 @@ const startDeviceHub = Effect.fn("DeviceHubProcess.start")(function* (input) {
44944
45057
  String(port),
44945
45058
  "--host",
44946
45059
  LOOPBACK_HOST,
45060
+ ...input.platform ? ["--platform", input.platform] : [],
44947
45061
  "--hide-sidebar",
44948
45062
  "--hide-boot-device"
44949
45063
  ], {
@@ -45694,6 +45808,11 @@ const deviceHostEnvironment = (environment, sdkRoot, hostPlatform, path) => {
45694
45808
  ].join(hostPlatform === "win32" ? ";" : ":")
45695
45809
  } : environment;
45696
45810
  };
45811
+ /** Unavailable Android tooling must not turn a valid iOS inventory into a partial failure. */
45812
+ function deviceHubPlatform(platforms) {
45813
+ const available = platforms.filter((platform) => platform.available);
45814
+ return available.length === 1 ? available[0].platform : void 0;
45815
+ }
45697
45816
  //#endregion
45698
45817
  //#region src/device/LocalDeviceHost.ts
45699
45818
  const COMMAND_TIMEOUT_MS$1 = 2e4;
@@ -45767,9 +45886,11 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
45767
45886
  cause
45768
45887
  })));
45769
45888
  yield* onPhase("starting");
45889
+ const hubPlatform = deviceHubPlatform(yield* Effect.all([platformAvailability("ios"), platformAvailability("android")]));
45770
45890
  const started = yield* startDeviceHub({
45771
45891
  tool,
45772
- environment: hostEnvironment
45892
+ environment: hostEnvironment,
45893
+ ...hubPlatform ? { platform: hubPlatform } : {}
45773
45894
  }).pipe(Effect.provideService(NetService, net), Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner), Effect.provideService(HttpClient.HttpClient, http), Effect.provideService(Scope.Scope, scope));
45774
45895
  hub = started;
45775
45896
  const dist = path.join(tool.installDir, "node_modules", "expo-device-hub", "vendor", "serve-sim", "dist");
@@ -47527,7 +47648,7 @@ const make$78 = Effect.gen(function* () {
47527
47648
  } else {
47528
47649
  yield* Effect.logDebug("startup phase: browser open check");
47529
47650
  const startupBrowserTarget = yield* resolveStartupBrowserTarget;
47530
- if (serverConfig.mode !== "desktop") yield* Effect.logInfo("Authentication required. Open P4Code using the pairing URL.").pipe(Effect.annotateLogs({ pairingUrl: startupBrowserTarget }));
47651
+ if (serverConfig.mode !== "desktop") yield* Effect.logInfo("Authentication required. Open P4 Code using the pairing URL.").pipe(Effect.annotateLogs({ pairingUrl: startupBrowserTarget }));
47531
47652
  yield* runStartupPhase("browser.open", maybeOpenBrowser(startupBrowserTarget));
47532
47653
  }
47533
47654
  yield* Effect.logDebug("startup phase: complete");
@@ -52173,7 +52294,7 @@ const prepareAntigravityProfile = Effect.fn("prepareAntigravityProfile")(functio
52173
52294
  "--",
52174
52295
  "%s"
52175
52296
  ].map(quoteBrowserArgument).join(" ");
52176
- if (browserCommand.includes(platform === "win32" ? ";" : ":") || helperExecutable.includes("\r") || helperExecutable.includes("\n") || helperExecutable.includes("\0") || helperExecutable.includes("%s")) return yield* authSupportError("The P4Code runtime path cannot be used to suppress Antigravity browser launches.");
52297
+ if (browserCommand.includes(platform === "win32" ? ";" : ":") || helperExecutable.includes("\r") || helperExecutable.includes("\n") || helperExecutable.includes("\0") || helperExecutable.includes("%s")) return yield* authSupportError("The P4 Code runtime path cannot be used to suppress Antigravity browser launches.");
52177
52298
  const geminiHome = path.resolve(input.profileDirectory);
52178
52299
  const acpDirectory = path.join(geminiHome, "antigravity-acp");
52179
52300
  const profile = {
@@ -52920,7 +53041,7 @@ const makeProviderAuthService = Effect.gen(function* () {
52920
53041
  if (!instance?.auth) return yield* new ProviderSetupError({
52921
53042
  instanceId,
52922
53043
  operation,
52923
- detail: instance ? "This provider does not support sign-in in P4Code." : "This provider instance is no longer available."
53044
+ detail: instance ? "This provider does not support sign-in in P4 Code." : "This provider instance is no longer available."
52924
53045
  });
52925
53046
  return instance.auth;
52926
53047
  });
@@ -53113,6 +53234,489 @@ const remoteComputerUseBindingsLayer = Layer.effect(RemoteComputerUseBindings, E
53113
53234
  });
53114
53235
  }));
53115
53236
  //#endregion
53237
+ //#region src/device/DeviceCommandProxy.ts
53238
+ var DeviceCommandProxyFailure = class extends Data.TaggedError("DeviceCommandProxyFailure") {};
53239
+ const COMMAND_TIMEOUT_MS = 3e4;
53240
+ const MAX_RESPONSE_BYTES$2 = 64 * 1024;
53241
+ const Reply = Schema$1.Struct({
53242
+ jsonrpc: Schema$1.Literal("2.0"),
53243
+ id: Schema$1.String,
53244
+ result: Schema$1.Struct({ ok: Schema$1.Boolean })
53245
+ });
53246
+ const make$75 = Effect.fn("DeviceCommandProxy.make")(function* () {
53247
+ const http = yield* HttpClient.HttpClient;
53248
+ const daemonSessions = /* @__PURE__ */ new WeakMap();
53249
+ return Effect.fn("DeviceCommandProxy.execute")(function* (endpoint, session, payload) {
53250
+ const input = yield* Schema$1.decodeUnknownEffect(DeviceCommandInput)(payload);
53251
+ if (input.hostId !== session.hostId || input.deviceId !== session.deviceId) return yield* new DeviceCommandProxyFailure({ message: "Target mismatch" });
53252
+ const origin = yield* Effect.try(() => new URL(endpoint.baseUrl));
53253
+ if (origin.protocol !== "http:" || origin.hostname !== "127.0.0.1" || !origin.port || origin.username || origin.password || origin.pathname !== "/" || origin.search || origin.hash) return yield* new DeviceCommandProxyFailure({ message: "Invalid owned daemon" });
53254
+ let daemonSession = daemonSessions.get(session);
53255
+ if (!daemonSession) {
53256
+ daemonSession = `p4-${NodeCrypto.randomUUID()}`;
53257
+ daemonSessions.set(session, daemonSession);
53258
+ }
53259
+ const id = NodeCrypto.randomUUID();
53260
+ const request = HttpClientRequest.post(`${origin.origin}/rpc`).pipe(HttpClientRequest.bodyJsonUnsafe({
53261
+ jsonrpc: "2.0",
53262
+ id,
53263
+ method: "agent_device.command",
53264
+ params: {
53265
+ token: endpoint.token,
53266
+ session: daemonSession,
53267
+ command: input.command,
53268
+ positionals: input.command === "press" ? [String(input.x), String(input.y)] : [input.text],
53269
+ flags: session.platform === "ios" ? {
53270
+ platform: "ios",
53271
+ udid: session.deviceId
53272
+ } : {
53273
+ platform: "android",
53274
+ serial: session.deviceId
53275
+ }
53276
+ }
53277
+ }));
53278
+ const response = yield* http.execute(request);
53279
+ if (response.status !== 200) return yield* new DeviceCommandProxyFailure({ message: "Command rejected" });
53280
+ let bytes = 0;
53281
+ const body = yield* collectUint8StreamText({
53282
+ stream: response.stream.pipe(Stream.mapEffect((chunk) => {
53283
+ bytes += chunk.byteLength;
53284
+ return bytes > MAX_RESPONSE_BYTES$2 ? Effect.fail(new DeviceCommandProxyFailure({ message: "Command response too large" })) : Effect.succeed(chunk);
53285
+ })),
53286
+ maxBytes: MAX_RESPONSE_BYTES$2
53287
+ });
53288
+ if (body.invalidUtf8 || body.truncated) return yield* new DeviceCommandProxyFailure({ message: "Invalid response" });
53289
+ const reply = yield* Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(Reply))(body.text);
53290
+ if (reply.id !== id || !reply.result.ok) return yield* new DeviceCommandProxyFailure({ message: "Command not acknowledged" });
53291
+ return { ok: true };
53292
+ }, Effect.scoped, Effect.timeout(Duration.millis(COMMAND_TIMEOUT_MS)), Effect.mapError(() => new DeviceOperationError({
53293
+ operation: "command",
53294
+ reason: "request_failed",
53295
+ cause: "Device command could not be completed."
53296
+ })));
53297
+ });
53298
+ var DeviceCommandProxy = class extends Context.Service()("@p4code/cli/device/DeviceCommandProxy") {};
53299
+ const layer$67 = Layer.effect(DeviceCommandProxy, make$75().pipe(Effect.map((execute) => ({ execute }))));
53300
+ //#endregion
53301
+ //#region src/device/DeviceScreenshot.ts
53302
+ const MAX_SCREENSHOT_BYTES = 8 * 1024 * 1024;
53303
+ var DeviceScreenshotFailure = class extends Data.TaggedError("DeviceScreenshotFailure") {};
53304
+ const MAX_DIMENSION = 16384;
53305
+ const MAX_PIXELS = 64 * 1024 * 1024;
53306
+ const SCREENSHOT_TIMEOUT_MS = 2e4;
53307
+ const PNG_HEADER_BYTES = 33;
53308
+ const PNG_CHUNK_OVERHEAD = 12;
53309
+ const PNG_SIGNATURE = Buffer.from([
53310
+ 137,
53311
+ 80,
53312
+ 78,
53313
+ 71,
53314
+ 13,
53315
+ 10,
53316
+ 26,
53317
+ 10
53318
+ ]);
53319
+ function pngDimensions(png) {
53320
+ const buffer = Buffer.from(png.buffer, png.byteOffset, png.byteLength);
53321
+ if (buffer.length < PNG_HEADER_BYTES || buffer.length > 8388608 || !buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE) || buffer.readUInt32BE(8) !== 13 || buffer.toString("ascii", 12, 16) !== "IHDR") throw new DeviceScreenshotFailure({ message: "Invalid PNG screenshot." });
53322
+ const width = buffer.readUInt32BE(16);
53323
+ const height = buffer.readUInt32BE(20);
53324
+ if (!width || !height || width > MAX_DIMENSION || height > MAX_DIMENSION || width * height > MAX_PIXELS) throw new DeviceScreenshotFailure({ message: "Screenshot dimensions exceed limits." });
53325
+ let offset = PNG_HEADER_BYTES;
53326
+ let imageData = false;
53327
+ let ended = false;
53328
+ while (offset + PNG_CHUNK_OVERHEAD <= buffer.length) {
53329
+ const length = buffer.readUInt32BE(offset);
53330
+ const type = buffer.toString("ascii", offset + 4, offset + 8);
53331
+ const next = offset + PNG_CHUNK_OVERHEAD + length;
53332
+ if (next > buffer.length || type === "IHDR") throw new DeviceScreenshotFailure({ message: "Invalid PNG chunk." });
53333
+ if (type === "IDAT") imageData = true;
53334
+ if (type === "IEND") {
53335
+ ended = length === 0 && next === buffer.length;
53336
+ break;
53337
+ }
53338
+ offset = next;
53339
+ }
53340
+ if (!imageData || !ended) throw new DeviceScreenshotFailure({ message: "Incomplete PNG screenshot." });
53341
+ return {
53342
+ width,
53343
+ height
53344
+ };
53345
+ }
53346
+ const make$74 = Effect.fn("DeviceScreenshot.make")(function* () {
53347
+ const http = yield* HttpClient.HttpClient;
53348
+ return Effect.fn("DeviceScreenshot.capture")(function* (ready, session) {
53349
+ const origin = yield* Effect.try(() => new URL(ready.hub.origin));
53350
+ if (origin.protocol !== "http:" || origin.hostname !== "127.0.0.1" || !origin.port || origin.username || origin.password || origin.pathname !== "/" || origin.search || origin.hash) return yield* new DeviceScreenshotFailure({ message: "Invalid owned hub." });
53351
+ const vendor = session.platform === "ios" ? "serve-sim" : "serve-emu";
53352
+ const response = yield* http.execute(HttpClientRequest.post(`${origin.origin}/vendor/${vendor}/api/screenshot?device=${encodeURIComponent(session.deviceId)}`));
53353
+ if (response.status !== 200) return yield* new DeviceScreenshotFailure({ message: "Screenshot rejected." });
53354
+ let bytes = 0;
53355
+ const chunks = [];
53356
+ yield* response.stream.pipe(Stream.runForEach((chunk) => Effect.gen(function* () {
53357
+ bytes += chunk.byteLength;
53358
+ if (bytes > 8388608) return yield* new DeviceScreenshotFailure({ message: "Screenshot too large." });
53359
+ chunks.push(chunk);
53360
+ })));
53361
+ const png = Buffer.concat(chunks, bytes);
53362
+ return {
53363
+ png,
53364
+ ...yield* Effect.try(() => pngDimensions(png))
53365
+ };
53366
+ }, Effect.scoped, Effect.timeout(Duration.millis(SCREENSHOT_TIMEOUT_MS)), Effect.mapError(() => new DeviceOperationError({
53367
+ operation: "screenshot",
53368
+ reason: "request_failed",
53369
+ cause: "Device screenshot could not be captured."
53370
+ })));
53371
+ });
53372
+ var DeviceScreenshot = class extends Context.Service()("@p4code/cli/device/DeviceScreenshot") {};
53373
+ const layer$66 = Layer.effect(DeviceScreenshot, make$74().pipe(Effect.map((capture) => ({ capture }))));
53374
+ //#endregion
53375
+ //#region src/device/DeviceHubRoute.ts
53376
+ const DEVICE_HUB_PROXY_PREFIX = "/api/device-hub";
53377
+ const MAX_ROUTE_LENGTH = 16 * 1024;
53378
+ const MAX_TICKET_LENGTH = 2048;
53379
+ const decodeTarget = Schema$1.decodeUnknownSync(DeviceSessionDetailInput);
53380
+ const RESOURCES = [
53381
+ "video.avcc",
53382
+ "video.mjpeg",
53383
+ "socket",
53384
+ "screenshot",
53385
+ "ax",
53386
+ "foreground"
53387
+ ];
53388
+ function segment(raw) {
53389
+ const value = decodeURIComponent(raw);
53390
+ if (!value || value === "." || value === ".." || /[%/\\\x00-\x1f\x7f]/.test(value) || encodeURIComponent(value) !== raw) throw new Error("Invalid device route segment.");
53391
+ return value;
53392
+ }
53393
+ /** Parse only P4 resources. Caller query parameters never reach the private hub. */
53394
+ function parseDeviceHubRoute(url, method, upgrade) {
53395
+ if (url.href.length > MAX_ROUTE_LENGTH || url.hash || method !== "GET") throw new Error("Invalid device route.");
53396
+ const parts = url.pathname.split("/");
53397
+ if (parts.length !== 10 || parts.slice(0, 3).join("/") !== "/api/device-hub" || parts[3] !== "thread" || parts[5] !== "host" || parts[7] !== "device") throw new Error("Invalid device route.");
53398
+ const resource = parts[9];
53399
+ if (!RESOURCES.some((value) => value === resource) || upgrade !== (resource === "socket")) throw new Error("Unsupported device resource.");
53400
+ const tickets = url.searchParams.getAll("wsTicket");
53401
+ if ([...url.searchParams.keys()].some((key) => key !== "wsTicket") || tickets.length > 1 || tickets.some((ticket) => !ticket || ticket.length > MAX_TICKET_LENGTH)) throw new Error("Invalid device query.");
53402
+ return {
53403
+ target: decodeTarget({
53404
+ threadId: segment(parts[4]),
53405
+ hostId: segment(parts[6]),
53406
+ deviceId: segment(parts[8])
53407
+ }),
53408
+ resource,
53409
+ requiredScope: resource === "socket" ? AuthOrchestrationOperateScope : AuthOrchestrationReadScope
53410
+ };
53411
+ }
53412
+ /** Resolve from the authoritative session, never from a caller-supplied upstream URL. */
53413
+ function resolveDeviceHubRoute(route, session, origin) {
53414
+ if (route.target.threadId !== session.threadId || route.target.hostId !== session.hostId || route.target.deviceId !== session.deviceId) throw new Error("Device session changed.");
53415
+ const hub = new URL(origin);
53416
+ if (hub.protocol !== "http:" || hub.hostname !== "127.0.0.1" || !hub.port || hub.username || hub.password || hub.pathname !== "/" || hub.search || hub.hash) throw new Error("Invalid owned device hub.");
53417
+ const device = encodeURIComponent(session.deviceId);
53418
+ let path;
53419
+ let method = "GET";
53420
+ if (session.platform === "ios") switch (route.resource) {
53421
+ case "video.avcc":
53422
+ path = `/vendor/serve-sim/helper/${device}/stream.avcc`;
53423
+ break;
53424
+ case "video.mjpeg":
53425
+ path = `/vendor/serve-sim/helper/${device}/stream.mjpeg`;
53426
+ break;
53427
+ case "socket":
53428
+ path = `/vendor/serve-sim/helper/ws?device=${device}`;
53429
+ break;
53430
+ case "screenshot":
53431
+ path = `/vendor/serve-sim/api/screenshot?device=${device}`;
53432
+ method = "POST";
53433
+ break;
53434
+ case "ax":
53435
+ path = `/vendor/serve-sim/helper/${device}/ax`;
53436
+ break;
53437
+ case "foreground":
53438
+ path = `/vendor/serve-sim/helper/${device}/foreground`;
53439
+ break;
53440
+ }
53441
+ else switch (route.resource) {
53442
+ case "socket":
53443
+ path = `/vendor/serve-emu/ws?device=${device}&frame-meta=1`;
53444
+ break;
53445
+ case "screenshot":
53446
+ path = `/vendor/serve-emu/api/screenshot?device=${device}`;
53447
+ method = "POST";
53448
+ break;
53449
+ case "ax":
53450
+ path = `/vendor/serve-emu/api/accessibility?device=${device}`;
53451
+ break;
53452
+ default: throw new Error("Device resource unavailable on this platform.");
53453
+ }
53454
+ const upstream = new URL(path, hub);
53455
+ if (route.resource === "socket") upstream.protocol = "ws:";
53456
+ return {
53457
+ url: upstream.href,
53458
+ method,
53459
+ streaming: route.resource === "video.avcc" || route.resource === "video.mjpeg" || route.resource === "socket"
53460
+ };
53461
+ }
53462
+ //#endregion
53463
+ //#region src/mcp/McpInvocationContext.ts
53464
+ var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
53465
+ const requireMcpCapability = Effect.fn("mcp.requireCapability")(function* (capability) {
53466
+ const invocation = yield* McpInvocationContext;
53467
+ if (!invocation.capabilities.has(capability)) return yield* new PreviewAutomationUnavailableError({
53468
+ capability,
53469
+ environmentId: invocation.environmentId,
53470
+ threadId: invocation.threadId,
53471
+ providerSessionId: invocation.providerSessionId,
53472
+ providerInstanceId: invocation.providerInstanceId
53473
+ });
53474
+ return invocation;
53475
+ });
53476
+ /**
53477
+ * The task-board counterpart of {@link requireMcpCapability}. The two are
53478
+ * separate because each capability reports its own absence with the error type
53479
+ * its toolkit declares as a failure, and those unions do not overlap.
53480
+ */
53481
+ const requireTaskCapability = Effect.fn("mcp.requireTaskCapability")(function* () {
53482
+ const invocation = yield* McpInvocationContext;
53483
+ if (!invocation.capabilities.has("tasks")) return yield* new TaskToolUnavailableError({
53484
+ capability: "tasks",
53485
+ environmentId: invocation.environmentId,
53486
+ threadId: invocation.threadId,
53487
+ providerSessionId: invocation.providerSessionId,
53488
+ providerInstanceId: invocation.providerInstanceId
53489
+ });
53490
+ return invocation;
53491
+ });
53492
+ /**
53493
+ * The watch capability's guard is two checks, not one: the capability must be
53494
+ * present AND the requested thread must be in the explicit grant set. The two
53495
+ * failures are distinct errors so a watcher can tell "this session cannot
53496
+ * watch at all" apart from "not this thread".
53497
+ */
53498
+ const requireWatchCapability = Effect.fn("mcp.requireWatchCapability")(function* (watchedThreadId) {
53499
+ const invocation = yield* McpInvocationContext;
53500
+ if (!invocation.capabilities.has("watch")) return yield* new WatchToolUnavailableError({
53501
+ capability: "watch",
53502
+ environmentId: invocation.environmentId,
53503
+ threadId: invocation.threadId,
53504
+ providerSessionId: invocation.providerSessionId,
53505
+ providerInstanceId: invocation.providerInstanceId
53506
+ });
53507
+ if (!invocation.watchThreadIds?.has(watchedThreadId)) return yield* new ThreadWatchNotPermittedError({ threadId: watchedThreadId });
53508
+ return invocation;
53509
+ });
53510
+ /**
53511
+ * The advise guard mirrors the watch guard's two checks - capability present
53512
+ * AND thread in the explicit grant - because advising carries strictly more
53513
+ * power than watching. A watch-only credential fails the first check here no
53514
+ * matter what threads it can read.
53515
+ */
53516
+ const requireAdviseCapability = Effect.fn("mcp.requireAdviseCapability")(function* (advisedThreadId) {
53517
+ const invocation = yield* McpInvocationContext;
53518
+ if (!invocation.capabilities.has("advise")) return yield* new AdviseToolUnavailableError({
53519
+ capability: "advise",
53520
+ environmentId: invocation.environmentId,
53521
+ threadId: invocation.threadId,
53522
+ providerSessionId: invocation.providerSessionId,
53523
+ providerInstanceId: invocation.providerInstanceId
53524
+ });
53525
+ if (!invocation.adviseThreadIds?.has(advisedThreadId)) return yield* new ThreadAdviseNotPermittedError({ threadId: advisedThreadId });
53526
+ return invocation;
53527
+ });
53528
+ /** Third of the trio, for the same reason the second exists. */
53529
+ const requireThreadCapability = Effect.fn("mcp.requireThreadCapability")(function* () {
53530
+ const invocation = yield* McpInvocationContext;
53531
+ if (!invocation.capabilities.has("threads")) return yield* new ThreadToolUnavailableError({
53532
+ capability: "threads",
53533
+ environmentId: invocation.environmentId,
53534
+ threadId: invocation.threadId,
53535
+ providerSessionId: invocation.providerSessionId,
53536
+ providerInstanceId: invocation.providerInstanceId
53537
+ });
53538
+ return invocation;
53539
+ });
53540
+ /**
53541
+ * The thread a control tool may act on, given what it was asked to act on.
53542
+ *
53543
+ * Two checks like `requireWatchCapability`, and for the same reason: the
53544
+ * capability says this session controls threads at all, the grant says which.
53545
+ * An omitted id resolves to the session's own thread, which is always in the
53546
+ * grant and is why the common call needs no id and so cannot name a wrong one.
53547
+ */
53548
+ const requireThreadControlTarget = Effect.fn("mcp.requireThreadControlTarget")(function* (requested) {
53549
+ const invocation = yield* requireThreadCapability();
53550
+ if (requested === void 0 || requested === invocation.threadId) return {
53551
+ invocation,
53552
+ threadId: invocation.threadId
53553
+ };
53554
+ if (!invocation.controlThreadIds?.has(requested)) return yield* new ThreadControlNotPermittedError({ threadId: requested });
53555
+ return {
53556
+ invocation,
53557
+ threadId: requested
53558
+ };
53559
+ });
53560
+ /**
53561
+ * The guard on starting a thread, which is a different question from acting on
53562
+ * one: it is not "which thread" but "may this session make more of them".
53563
+ */
53564
+ const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* (fusion = false) {
53565
+ const invocation = yield* requireThreadCapability();
53566
+ if (invocation.mayCreateThreads !== true && !(fusion && invocation.mayCreateFusionPairs === true)) return yield* new ThreadSpawnNotPermittedError({
53567
+ threadId: invocation.threadId,
53568
+ detail: "this thread was itself started by an agent, and spawning goes one level deep so a runaway loop has a bound"
53569
+ });
53570
+ return invocation;
53571
+ });
53572
+ //#endregion
53573
+ //#region src/mcp/DeviceInvocation.ts
53574
+ const isDeviceToolUnavailableError = Schema$1.is(DeviceToolUnavailableError);
53575
+ const isDeviceActionUnavailableError = Schema$1.is(DeviceActionUnavailableError);
53576
+ /** Internal bridge; tool payloads never choose thread identity or daemon credentials. */
53577
+ const withDeviceInvocation = (execute) => Effect.gen(function* () {
53578
+ const invocation = yield* McpInvocationContext;
53579
+ const service = yield* DeviceService;
53580
+ const lifetime = invocation.authorizationLifetime;
53581
+ const denied = () => new DeviceToolUnavailableError({ reason: "Device command unavailable or authorization changed." });
53582
+ if (!invocation.capabilities.has("devices") || !lifetime?.revocation || lifetime.revoked) return yield* denied();
53583
+ 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()));
53584
+ return yield* Effect.raceFirst(work, Deferred.await(lifetime.revocation).pipe(Effect.andThen(Effect.fail(denied()))));
53585
+ });
53586
+ const withDeviceSession = (target, execute) => withDeviceInvocation((service, threadId) => service.withAgentCommand({
53587
+ hostId: target.hostId,
53588
+ deviceId: target.deviceId,
53589
+ threadId
53590
+ }, execute));
53591
+ //#endregion
53592
+ //#region src/mcp/ComputerUseDevices.ts
53593
+ const MAX_AX_BYTES = 512 * 1024;
53594
+ const AX_TIMEOUT_MS = 1e4;
53595
+ const MAX_AX_EXTENT = 32768;
53596
+ const MIN_AX_EXTENT = 2;
53597
+ const AxFrames = Schema$1.Array(Schema$1.Struct({ frame: Schema$1.Struct({
53598
+ x: Schema$1.Number,
53599
+ y: Schema$1.Number,
53600
+ width: Schema$1.Number.check(Schema$1.isBetween({
53601
+ minimum: MIN_AX_EXTENT,
53602
+ maximum: MAX_AX_EXTENT
53603
+ })),
53604
+ height: Schema$1.Number.check(Schema$1.isBetween({
53605
+ minimum: MIN_AX_EXTENT,
53606
+ maximum: MAX_AX_EXTENT
53607
+ }))
53608
+ }) }));
53609
+ const readAxFrames = Schema$1.decodeUnknownOption(AxFrames);
53610
+ const decodeAxDocument = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(Schema$1.Unknown));
53611
+ /** Reuse consent and authoritative device leases. The helper never receives daemon credentials. */
53612
+ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* () {
53613
+ const devices = yield* DeviceService;
53614
+ const screenshots = yield* DeviceScreenshot;
53615
+ const commands = yield* DeviceCommandProxy;
53616
+ const http = yield* HttpClient.HttpClient;
53617
+ const stale = () => new DeviceOperationError({
53618
+ operation: "command",
53619
+ reason: "request_failed",
53620
+ cause: "Device lease changed. Select this host/device again."
53621
+ });
53622
+ return (scope, input) => withDeviceInvocation((service, threadId) => Effect.gen(function* () {
53623
+ if (input.method === "list") {
53624
+ const state = yield* service.agentList;
53625
+ return {
53626
+ hosts: state.hosts,
53627
+ devices: state.devices,
53628
+ hostStatuses: state.hostStatuses,
53629
+ open: state.sessions.filter((session) => session.threadId === threadId)
53630
+ };
53631
+ }
53632
+ if (input.method === "open") {
53633
+ const state = yield* service.agentList;
53634
+ const device = state.devices.find((device) => device.hostId === input.hostId && device.id === input.deviceId && device.platform === input.platform);
53635
+ if (!device) return yield* stale();
53636
+ const session = yield* service.agentOpen({
53637
+ threadId,
53638
+ hostId: input.hostId,
53639
+ deviceId: input.deviceId,
53640
+ platform: input.platform
53641
+ });
53642
+ if (!session.leaseId) return yield* stale();
53643
+ return {
53644
+ device,
53645
+ leaseId: session.leaseId,
53646
+ hostLabel: state.hosts.find((host) => host.id === device.hostId)?.label ?? device.hostId
53647
+ };
53648
+ }
53649
+ const target = input.method === "command" ? input.command : input;
53650
+ if (input.method === "close") {
53651
+ yield* service.agentClose({
53652
+ threadId,
53653
+ hostId: target.hostId,
53654
+ deviceId: target.deviceId,
53655
+ expectedLeaseId: input.leaseId
53656
+ });
53657
+ return { closed: true };
53658
+ }
53659
+ if (input.method === "command") return yield* service.withAgentCommand({
53660
+ threadId,
53661
+ hostId: target.hostId,
53662
+ deviceId: target.deviceId
53663
+ }, (endpoint, session) => {
53664
+ if (session.leaseId !== input.leaseId) return Effect.fail(stale());
53665
+ return commands.execute(endpoint, session, input.command);
53666
+ });
53667
+ return yield* service.withAgentDevice({
53668
+ threadId,
53669
+ hostId: target.hostId,
53670
+ deviceId: target.deviceId
53671
+ }, (ready, session) => Effect.gen(function* () {
53672
+ if (session.leaseId !== input.leaseId) return yield* stale();
53673
+ if (input.method === "screenshot") {
53674
+ const capture = yield* screenshots.capture(ready, session);
53675
+ return {
53676
+ mimeType: "image/png",
53677
+ data: capture.png.toString("base64"),
53678
+ width: capture.width,
53679
+ height: capture.height
53680
+ };
53681
+ }
53682
+ if (session.platform !== "ios") return yield* new DeviceToolUnavailableError({ reason: "CUA accessibility state is currently supported only for iOS Simulator. Use a screenshot for this device." });
53683
+ const route = resolveDeviceHubRoute({
53684
+ target: {
53685
+ threadId,
53686
+ hostId: target.hostId,
53687
+ deviceId: target.deviceId
53688
+ },
53689
+ resource: "ax",
53690
+ requiredScope: AuthOrchestrationReadScope
53691
+ }, session, ready.hub.origin);
53692
+ const response = yield* http.execute(HttpClientRequest.get(route.url));
53693
+ if (response.status !== 200) return yield* new DeviceToolUnavailableError({ reason: "Device hub accessibility state is unavailable for this simulator. Use getScreenshot() or check the hub helper." });
53694
+ const body = yield* collectUint8StreamText({
53695
+ stream: response.stream,
53696
+ maxBytes: MAX_AX_BYTES
53697
+ });
53698
+ if (body.truncated || body.invalidUtf8) return yield* new DeviceToolUnavailableError({ reason: "Device accessibility state exceeds the supported size." });
53699
+ const accessibility = yield* decodeAxDocument(body.text);
53700
+ const frames = readAxFrames(accessibility);
53701
+ const viewport = Option.isSome(frames) ? frames.value[0]?.frame : void 0;
53702
+ return {
53703
+ ...viewport ? { viewport } : {},
53704
+ hostId: session.hostId,
53705
+ deviceId: session.deviceId,
53706
+ leaseId: session.leaseId,
53707
+ accessibility
53708
+ };
53709
+ }).pipe(Effect.scoped, Effect.timeout(AX_TIMEOUT_MS), Effect.mapError((error) => new DeviceOperationError({
53710
+ operation: "command",
53711
+ reason: "request_failed",
53712
+ cause: error.message
53713
+ }))));
53714
+ })).pipe(Effect.provideService(McpInvocationContext, scope), Effect.provideService(DeviceService, devices), Effect.mapError((error) => new ComputerUseError({
53715
+ reason: "unavailable",
53716
+ detail: error.message
53717
+ })));
53718
+ });
53719
+ //#endregion
53116
53720
  //#region src/mcp/ComputerUseBroker.ts
53117
53721
  const COMPUTER_USE_HELPER_CREDENTIAL_TTL_MS = 300 * 1e3;
53118
53722
  const HELPER_CREDENTIAL_BYTES = 32;
@@ -53133,7 +53737,7 @@ const hostSession = (scope) => ({
53133
53737
  providerSessionId: scope.providerSessionId
53134
53738
  });
53135
53739
  var ComputerUseBroker = class extends Context.Service()("@p4code/cli/mcp/ComputerUseBroker") {};
53136
- const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53740
+ const layer$65 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53137
53741
  const serviceScope = yield* Scope.Scope;
53138
53742
  const crypto = yield* Crypto.Crypto;
53139
53743
  const environment = yield* ServerEnvironment;
@@ -53322,7 +53926,12 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53322
53926
  state: "stopped"
53323
53927
  });
53324
53928
  }
53325
- if (report.state !== "active") yield* publish();
53929
+ if (report.state === "active" && state.state === "active" && (report.previewApp !== void 0 || report.deviceControl !== void 0)) states.set(key, {
53930
+ ...state,
53931
+ ...report.previewApp !== void 0 ? { previewApp: report.previewApp } : {},
53932
+ ...report.deviceControl !== void 0 ? { deviceControl: report.deviceControl } : {}
53933
+ });
53934
+ if (report.state !== "active" || report.previewApp !== void 0 || report.deviceControl !== void 0) yield* publish();
53326
53935
  }, admission.withPermits(1));
53327
53936
  const control = Effect.fn("ComputerUseBroker.control")(function* (input) {
53328
53937
  const targets = yield* admission.withPermits(1)(Effect.gen(function* () {
@@ -53347,6 +53956,53 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53347
53956
  }
53348
53957
  yield* publish();
53349
53958
  }, controlAdmission.withPermits(1), Effect.uninterruptible);
53959
+ const capturePreview = Effect.fn("ComputerUseBroker.capturePreview")(function* (session) {
53960
+ const key = scopeKey(session);
53961
+ const state = states.get(key);
53962
+ const connection = state ? connections.get(state.host.hostId) : void 0;
53963
+ if (!state || state.state !== "active" || stoppedThreads.has(session.threadId) || session.environmentId !== environmentId || state.session.generationId !== session.generationId || !connection || connection.host.connectionId !== state.host.connectionId || leases.get(key) !== connection) return yield* new ComputerUseError({
53964
+ reason: "unavailable",
53965
+ detail: "This Computer Use session is no longer active."
53966
+ });
53967
+ yield* authorize(connection.owner);
53968
+ if (pending.size >= MAX_PENDING_REQUESTS) return yield* new ComputerUseError({
53969
+ reason: "busy",
53970
+ detail: "Computer Use is busy."
53971
+ });
53972
+ const requestId = yield* crypto.randomUUIDv4.pipe(Effect.orDie);
53973
+ const completion = yield* Deferred.make();
53974
+ pending.set(requestId, {
53975
+ connection,
53976
+ completion,
53977
+ scopeKey: `preview:${key}`
53978
+ });
53979
+ return yield* Effect.gen(function* () {
53980
+ yield* Queue.offer(connection.queue, {
53981
+ type: "request",
53982
+ request: {
53983
+ requestId,
53984
+ hostId: connection.host.hostId,
53985
+ connectionId: connection.host.connectionId,
53986
+ session: state.session,
53987
+ operation: "preview"
53988
+ }
53989
+ });
53990
+ const output = yield* Deferred.await(completion).pipe(Effect.timeout(COMPUTER_USE_CONTROL_ACK_TIMEOUT_MS), Effect.mapError(() => new ComputerUseError({
53991
+ reason: "unavailable",
53992
+ detail: "Live view is unavailable. Retry after the host reconnects."
53993
+ })));
53994
+ const current = states.get(key);
53995
+ if (!output.preview || !current || current.state !== "active" || current.session.generationId !== session.generationId || connections.get(state.host.hostId) !== connection || leases.get(key) !== connection) return yield* new ComputerUseError({
53996
+ reason: "unavailable",
53997
+ detail: "This live view has ended."
53998
+ });
53999
+ return {
54000
+ session: state.session,
54001
+ host: state.host,
54002
+ frame: output.preview
54003
+ };
54004
+ }).pipe(Effect.ensuring(Effect.sync(() => pending.delete(requestId))));
54005
+ });
53350
54006
  return ComputerUseBroker.of({
53351
54007
  attachVerifiedHelper: (binding) => Effect.gen(function* () {
53352
54008
  if (binding.host.environmentId !== environmentId || !binding.helperIdentity || !binding.desktopSessionId) return yield* deny();
@@ -53411,6 +54067,7 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53411
54067
  report,
53412
54068
  control,
53413
54069
  controls: SubscriptionRef.changes(controls),
54070
+ preview: (session) => Stream.fromEffect(capturePreview(session)).pipe(Stream.repeat(Schedule.spaced(500))),
53414
54071
  list: Effect.sync(() => [...connections.values()].map((entry) => entry.host)),
53415
54072
  connect: (owner, host) => authorize(owner).pipe(Effect.as(Stream.unwrap(Effect.acquireRelease(admission.withPermits(1)(acquire(owner, host)), (connection) => revokeHelper(connection.owner)).pipe(Effect.map((connection) => Stream.fromQueue(connection.queue)))))),
53416
54073
  respond: Effect.fn("ComputerUseBroker.respond")(function* (owner, response) {
@@ -53423,6 +54080,13 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53423
54080
  if (response.result.ok) yield* Deferred.succeed(request.completion, response.result.output);
53424
54081
  else yield* Deferred.fail(request.completion, response.result.error);
53425
54082
  }),
54083
+ device: Effect.fn("ComputerUseBroker.device")(function* (owner, input, execute) {
54084
+ yield* authorize(owner);
54085
+ const request = pending.get(input.requestId);
54086
+ const invocation = request?.invocation;
54087
+ if (!request || !invocation || request.connection.owner !== owner || request.connection.host.hostId !== input.hostId || request.connection.host.connectionId !== input.connectionId || connections.get(input.hostId) !== request.connection || leases.get(request.scopeKey) !== request.connection || stoppedThreads.has(invocation.threadId)) return yield* deny();
54088
+ return yield* Effect.raceFirst(execute(invocation).pipe(Effect.tap(() => pending.get(input.requestId) === request ? Effect.void : Effect.fail(deny()))), Deferred.await(request.completion).pipe(Effect.ignore, Effect.andThen(Effect.fail(deny()))));
54089
+ }),
53426
54090
  invoke: (scope, input, hostId) => Effect.uninterruptibleMask((restore) => Effect.gen(function* () {
53427
54091
  const { requestId, connection, completion, request } = yield* admission.withPermits(1)(Effect.gen(function* () {
53428
54092
  if (scope.authorizationLifetime?.revoked === true || !scope.capabilities.has("computer-use") || scope.environmentId !== environmentId) return yield* deny();
@@ -53466,7 +54130,8 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53466
54130
  pending.set(requestId, {
53467
54131
  connection,
53468
54132
  completion,
53469
- scopeKey: key
54133
+ scopeKey: key,
54134
+ invocation: scope
53470
54135
  });
53471
54136
  return {
53472
54137
  requestId,
@@ -53510,9 +54175,12 @@ const layer$67 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
53510
54175
  }));
53511
54176
  //#endregion
53512
54177
  //#region src/mcp/ComputerUseDesktopTransport.ts
54178
+ const COMPUTER_USE_HEARTBEAT_MS = 3e4;
54179
+ const keepComputerUseTransportAlive = (stream) => stream.pipe(Stream.merge(Stream.fromEffect(Effect.sleep(COMPUTER_USE_HEARTBEAT_MS).pipe(Effect.as({ type: "heartbeat" }))).pipe(Stream.forever), { haltStrategy: "left" }));
53513
54180
  const Registration = Schema$1.Struct({
53514
54181
  host: ComputerUseHostRegistration,
53515
- helperIdentity: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(200))
54182
+ helperIdentity: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(200)),
54183
+ heartbeat: Schema$1.optional(Schema$1.Boolean)
53516
54184
  });
53517
54185
  const denied = () => new ComputerUseError({
53518
54186
  reason: "denied",
@@ -53592,9 +54260,30 @@ const connect = HttpRouter.add("POST", "/internal/computer-use/connect", Effect.
53592
54260
  connectionId: helper.connectionId
53593
54261
  }), events);
53594
54262
  }));
53595
- return HttpServerResponse.stream(messages.pipe(Stream.map((message) => new TextEncoder().encode(JSON.stringify(message) + "\n"))), {
54263
+ return HttpServerResponse.stream((input.heartbeat ? keepComputerUseTransportAlive(messages) : messages).pipe(Stream.map((message) => new TextEncoder().encode(JSON.stringify(message) + "\n"))), {
53596
54264
  contentType: "application/x-ndjson",
53597
- headers: { "cache-control": "no-store" }
54265
+ headers: {
54266
+ "cache-control": "no-store",
54267
+ "x-accel-buffering": "no"
54268
+ }
54269
+ });
54270
+ }).pipe(Effect.catch(failure$1)));
54271
+ const decodeDeviceRequest = Schema$1.decodeUnknownEffect(ComputerUseDeviceRequest);
54272
+ const device = HttpRouter.add("POST", "/internal/computer-use/device", Effect.gen(function* () {
54273
+ const request = yield* HttpServerRequest.HttpServerRequest;
54274
+ const broker = yield* ComputerUseBroker;
54275
+ const execute = yield* makeComputerUseDevices();
54276
+ const input = yield* decodeDeviceRequest(yield* request.json);
54277
+ const result = yield* broker.device(bearer(request), input, (scope) => execute(scope, input.operation)).pipe(Effect.map((value) => ({
54278
+ ok: true,
54279
+ value
54280
+ })), Effect.catch((error) => Effect.succeed({
54281
+ ok: false,
54282
+ error
54283
+ })));
54284
+ return HttpServerResponse.jsonUnsafe({
54285
+ callId: input.callId,
54286
+ result
53598
54287
  });
53599
54288
  }).pipe(Effect.catch(failure$1)));
53600
54289
  const respond = HttpRouter.add("POST", "/internal/computer-use/respond", Effect.gen(function* () {
@@ -53639,7 +54328,7 @@ const renew = HttpRouter.add("POST", "/internal/computer-use/renew", Effect.gen(
53639
54328
  if (binding.trust) yield* (yield* RemoteComputerUseBindings).touch(bearer(request));
53640
54329
  return HttpServerResponse.empty({ status: 204 });
53641
54330
  }).pipe(Effect.catch(failure$1)));
53642
- const layer$66 = Layer.mergeAll(exchange, hubForward, hubExchange, connect, respond, report, environment, renew).pipe(Layer.provide(remoteComputerUseBindingsLayer));
54331
+ const layer$64 = Layer.mergeAll(exchange, hubForward, hubExchange, connect, respond, device, report, environment, renew).pipe(Layer.provide(remoteComputerUseBindingsLayer));
53643
54332
  //#endregion
53644
54333
  //#region src/device/DeviceHubSocketProtocol.ts
53645
54334
  const MAX_DEVICE_INPUT_BYTES = 8 * 1024;
@@ -53852,94 +54541,6 @@ const bridgeDeviceSockets = Effect.fn("DeviceHubSocketBridge.bridge")(function*
53852
54541
  }));
53853
54542
  });
53854
54543
  //#endregion
53855
- //#region src/device/DeviceHubRoute.ts
53856
- const DEVICE_HUB_PROXY_PREFIX = "/api/device-hub";
53857
- const MAX_ROUTE_LENGTH = 16 * 1024;
53858
- const MAX_TICKET_LENGTH = 2048;
53859
- const decodeTarget = Schema$1.decodeUnknownSync(DeviceSessionDetailInput);
53860
- const RESOURCES = [
53861
- "video.avcc",
53862
- "video.mjpeg",
53863
- "socket",
53864
- "screenshot",
53865
- "ax",
53866
- "foreground"
53867
- ];
53868
- function segment(raw) {
53869
- const value = decodeURIComponent(raw);
53870
- if (!value || value === "." || value === ".." || /[%/\\\x00-\x1f\x7f]/.test(value) || encodeURIComponent(value) !== raw) throw new Error("Invalid device route segment.");
53871
- return value;
53872
- }
53873
- /** Parse only P4 resources. Caller query parameters never reach the private hub. */
53874
- function parseDeviceHubRoute(url, method, upgrade) {
53875
- if (url.href.length > MAX_ROUTE_LENGTH || url.hash || method !== "GET") throw new Error("Invalid device route.");
53876
- const parts = url.pathname.split("/");
53877
- if (parts.length !== 10 || parts.slice(0, 3).join("/") !== "/api/device-hub" || parts[3] !== "thread" || parts[5] !== "host" || parts[7] !== "device") throw new Error("Invalid device route.");
53878
- const resource = parts[9];
53879
- if (!RESOURCES.some((value) => value === resource) || upgrade !== (resource === "socket")) throw new Error("Unsupported device resource.");
53880
- const tickets = url.searchParams.getAll("wsTicket");
53881
- if ([...url.searchParams.keys()].some((key) => key !== "wsTicket") || tickets.length > 1 || tickets.some((ticket) => !ticket || ticket.length > MAX_TICKET_LENGTH)) throw new Error("Invalid device query.");
53882
- return {
53883
- target: decodeTarget({
53884
- threadId: segment(parts[4]),
53885
- hostId: segment(parts[6]),
53886
- deviceId: segment(parts[8])
53887
- }),
53888
- resource,
53889
- requiredScope: resource === "socket" ? AuthOrchestrationOperateScope : AuthOrchestrationReadScope
53890
- };
53891
- }
53892
- /** Resolve from the authoritative session, never from a caller-supplied upstream URL. */
53893
- function resolveDeviceHubRoute(route, session, origin) {
53894
- if (route.target.threadId !== session.threadId || route.target.hostId !== session.hostId || route.target.deviceId !== session.deviceId) throw new Error("Device session changed.");
53895
- const hub = new URL(origin);
53896
- if (hub.protocol !== "http:" || hub.hostname !== "127.0.0.1" || !hub.port || hub.username || hub.password || hub.pathname !== "/" || hub.search || hub.hash) throw new Error("Invalid owned device hub.");
53897
- const device = encodeURIComponent(session.deviceId);
53898
- let path;
53899
- let method = "GET";
53900
- if (session.platform === "ios") switch (route.resource) {
53901
- case "video.avcc":
53902
- path = `/vendor/serve-sim/helper/${device}/stream.avcc`;
53903
- break;
53904
- case "video.mjpeg":
53905
- path = `/vendor/serve-sim/helper/${device}/stream.mjpeg`;
53906
- break;
53907
- case "socket":
53908
- path = `/vendor/serve-sim/helper/ws?device=${device}`;
53909
- break;
53910
- case "screenshot":
53911
- path = `/vendor/serve-sim/api/screenshot?device=${device}`;
53912
- method = "POST";
53913
- break;
53914
- case "ax":
53915
- path = `/vendor/serve-sim/helper/${device}/ax`;
53916
- break;
53917
- case "foreground":
53918
- path = `/vendor/serve-sim/helper/${device}/foreground`;
53919
- break;
53920
- }
53921
- else switch (route.resource) {
53922
- case "socket":
53923
- path = `/vendor/serve-emu/ws?device=${device}&frame-meta=1`;
53924
- break;
53925
- case "screenshot":
53926
- path = `/vendor/serve-emu/api/screenshot?device=${device}`;
53927
- method = "POST";
53928
- break;
53929
- case "ax":
53930
- path = `/vendor/serve-emu/api/accessibility?device=${device}`;
53931
- break;
53932
- default: throw new Error("Device resource unavailable on this platform.");
53933
- }
53934
- const upstream = new URL(path, hub);
53935
- if (route.resource === "socket") upstream.protocol = "ws:";
53936
- return {
53937
- url: upstream.href,
53938
- method,
53939
- streaming: route.resource === "video.avcc" || route.resource === "video.mjpeg" || route.resource === "socket"
53940
- };
53941
- }
53942
- //#endregion
53943
54544
  //#region src/device/DeviceHubNodeSocket.ts
53944
54545
  const OPEN_TIMEOUT_MS = 1e4;
53945
54546
  const MAX_UPGRADE_HEAD_BYTES = 32 * 8206;
@@ -55105,7 +55706,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
55105
55706
  filePath: error.filePath,
55106
55707
  errorTag: error._tag
55107
55708
  }));
55108
- const make$75 = Effect.gen(function* () {
55709
+ const make$73 = Effect.gen(function* () {
55109
55710
  const fileSystem = yield* FileSystem.FileSystem;
55110
55711
  const path = yield* Path$1.Path;
55111
55712
  const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
@@ -55126,7 +55727,7 @@ const make$75 = Effect.gen(function* () {
55126
55727
  });
55127
55728
  return P4ProjectFileLoader.of({ load });
55128
55729
  });
55129
- const layer$65 = Layer.effect(P4ProjectFileLoader, make$75);
55730
+ const layer$63 = Layer.effect(P4ProjectFileLoader, make$73);
55130
55731
  //#endregion
55131
55732
  //#region src/project/ProjectFaviconResolver.ts
55132
55733
  /**
@@ -55201,7 +55802,7 @@ function extractIconHref(source) {
55201
55802
  return null;
55202
55803
  }
55203
55804
  const optionOnNotFound$1 = (effect) => effect.pipe(Effect.map(Option.some), Effect.catchTags({ PlatformError: (error) => error.reason._tag === "NotFound" ? Effect.succeed(Option.none()) : Effect.fail(error) }));
55204
- const make$74 = Effect.gen(function* () {
55805
+ const make$72 = Effect.gen(function* () {
55205
55806
  const fileSystem = yield* FileSystem.FileSystem;
55206
55807
  const path = yield* Path$1.Path;
55207
55808
  const workspacePaths = yield* WorkspacePaths;
@@ -55270,7 +55871,7 @@ const make$74 = Effect.gen(function* () {
55270
55871
  });
55271
55872
  return ProjectFaviconResolver.of({ resolvePath });
55272
55873
  });
55273
- const layer$64 = Layer.effect(ProjectFaviconResolver, make$74);
55874
+ const layer$62 = Layer.effect(ProjectFaviconResolver, make$72);
55274
55875
  //#endregion
55275
55876
  //#region src/assets/AssetAccess.ts
55276
55877
  const ASSET_ROUTE_PREFIX = "/api/assets";
@@ -55681,10 +56282,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
55681
56282
  //#endregion
55682
56283
  //#region src/observability/BrowserTraceCollector.ts
55683
56284
  var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
55684
- const make$73 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
56285
+ const make$71 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
55685
56286
  for (const record of records) sink.push(record);
55686
56287
  }) });
55687
- const layer$63 = (sink) => Layer.succeed(BrowserTraceCollector, make$73(sink));
56288
+ const layer$61 = (sink) => Layer.succeed(BrowserTraceCollector, make$71(sink));
55688
56289
  //#endregion
55689
56290
  //#region src/auth/http.ts
55690
56291
  const CREDENTIAL_RESPONSE_HEADERS = {
@@ -56826,7 +57427,7 @@ const defaultCancelTimeout = Duration.seconds(15);
56826
57427
  const defaultSessionLoadTimeout = Duration.seconds(90);
56827
57428
  const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
56828
57429
  var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
56829
- const make$72 = (options) => Effect.gen(function* () {
57430
+ const make$70 = (options) => Effect.gen(function* () {
56830
57431
  const crypto = yield* Crypto.Crypto;
56831
57432
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
56832
57433
  const runtimeScope = yield* Scope.Scope;
@@ -57230,7 +57831,7 @@ const make$72 = (options) => Effect.gen(function* () {
57230
57831
  notify: acp.raw.notify
57231
57832
  };
57232
57833
  });
57233
- const layer$62 = (options) => Layer.effect(AcpSessionRuntime, make$72(options));
57834
+ const layer$60 = (options) => Layer.effect(AcpSessionRuntime, make$70(options));
57234
57835
  function sessionConfigOptionsFromSetup(response) {
57235
57836
  return response?.configOptions ?? [];
57236
57837
  }
@@ -57624,7 +58225,7 @@ const buildAntigravityPrompt = Effect.fn("buildAntigravityPrompt")(function* (in
57624
58225
  });
57625
58226
  /** Normal launches reject browser login; only the auth flow supplies `onAuthorizationUrl`. */
57626
58227
  const makeAntigravityAcpRuntime = Effect.fn("makeAntigravityAcpRuntime")(function* (input) {
57627
- const context = yield* Layer.build(layer$62({
58228
+ const context = yield* Layer.build(layer$60({
57628
58229
  ...input,
57629
58230
  authMethodId: input.authMethod ?? "oauth-personal",
57630
58231
  resumeMethod: "resume",
@@ -60363,7 +60964,7 @@ const makeAntigravityProvider = Effect.fn("makeAntigravityProvider")(function* (
60363
60964
  status: "unknown",
60364
60965
  ...options.auth ? { type: options.auth.type } : {}
60365
60966
  },
60366
- message: settings.enabled ? "Checking Antigravity availability." : "Antigravity is disabled in P4Code settings."
60967
+ message: settings.enabled ? "Checking Antigravity availability." : "Antigravity is disabled in P4 Code settings."
60367
60968
  }
60368
60969
  }),
60369
60970
  setup: {
@@ -61601,7 +62202,7 @@ const BundledOnlyModelManifest = {
61601
62202
  refreshInBackground: Effect.void
61602
62203
  };
61603
62204
  Layer.succeed(ModelManifest, BundledOnlyModelManifest);
61604
- const make$71 = Effect.gen(function* () {
62205
+ const make$69 = Effect.gen(function* () {
61605
62206
  const fileSystem = yield* FileSystem.FileSystem;
61606
62207
  const path = yield* Path$1.Path;
61607
62208
  const config = yield* ServerConfig$1;
@@ -61646,7 +62247,7 @@ const make$71 = Effect.gen(function* () {
61646
62247
  refreshInBackground: Effect.forkIn(guardedRefresh, serviceScope).pipe(Effect.asVoid)
61647
62248
  });
61648
62249
  });
61649
- const layer$61 = Layer.effect(ModelManifest, make$71);
62250
+ const layer$59 = Layer.effect(ModelManifest, make$69);
61650
62251
  //#endregion
61651
62252
  //#region src/provider/ProviderDriver.ts
61652
62253
  function defaultProviderContinuationIdentity(input) {
@@ -61906,11 +62507,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
61906
62507
  detail: "This provider does not report account usage."
61907
62508
  }))))
61908
62509
  });
61909
- const make$70 = Effect.gen(function* () {
62510
+ const make$68 = Effect.gen(function* () {
61910
62511
  const registry = yield* ProviderInstanceRegistry;
61911
62512
  return makeTextGenerationFromRegistry(registry);
61912
62513
  });
61913
- const layer$60 = Layer.effect(TextGeneration, make$70);
62514
+ const layer$58 = Layer.effect(TextGeneration, make$68);
61914
62515
  //#endregion
61915
62516
  //#region src/provider/Layers/claudeUsageLimits.ts
61916
62517
  const SESSION_MINS$1 = 300;
@@ -62984,7 +63585,7 @@ const checkClaudeProviderStatus = Effect.fn("checkClaudeProviderStatus")(functio
62984
63585
  version: null,
62985
63586
  status: "warning",
62986
63587
  auth: { status: "unknown" },
62987
- message: "Claude is disabled in P4Code settings."
63588
+ message: "Claude is disabled in P4 Code settings."
62988
63589
  }
62989
63590
  });
62990
63591
  const versionProbe = yield* runClaudeCommand(claudeSettings, ["--version"], resolvedEnvironment).pipe(Effect.timeoutOption(DEFAULT_TIMEOUT_MS$5), Effect.result);
@@ -63102,7 +63703,7 @@ const makePendingClaudeProvider = (claudeSettings) => Effect.gen(function* () {
63102
63703
  version: null,
63103
63704
  status: "warning",
63104
63705
  auth: { status: "unknown" },
63105
- message: "Claude is disabled in P4Code settings."
63706
+ message: "Claude is disabled in P4 Code settings."
63106
63707
  }
63107
63708
  });
63108
63709
  return buildServerProvider({
@@ -63568,13 +64169,24 @@ function formatAskUserQuestionAnswers(answers) {
63568
64169
  *
63569
64170
  * They travel through the provider's session channel - Claude's system prompt
63570
64171
  * append, Codex's per-turn developer instructions - rather than as a prefix on
63571
- * every message. The block is about 650 tokens; a message-level copy sits in
63572
- * the conversation history for the rest of the thread, is re-read on every
63573
- * later API call, and is lost at compaction anyway. The session channel is
64172
+ * every message. Each resolved block runs to roughly a thousand tokens and
64173
+ * grows as the protocol does, so a message-level copy would sit in the
64174
+ * conversation history for the rest of the thread, be re-read on every later
64175
+ * API call, and be lost at compaction anyway. The session channel is
63574
64176
  * cached, never accumulates, and survives compaction. Messages then carry
63575
64177
  * only a one-line reference and the mutable `[fusion-pair]` metadata.
63576
64178
  */
63577
- const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder in an already-created native server pair. Server owns pairing and coordination. Do not inspect or invoke the Fusion skill, create/pair/rename threads, or announce/setup Fusion. Start the user's task directly. Before editing, create and maintain the phase list with your provider's step-tracking tool (Claude Code: TaskCreate for each phase, then TaskUpdate for status, or TodoWrite when that is the tool offered; Codex: update_plan), never the MCP task board tools - one entry per phase in order, exactly one in progress at a time, marked completed at each phase end - so phases render in the task banner. That list holds phase entries only for the whole task; keep step-level or per-file todos out of it. Name each phase in 3-6 words by its outcome, never by a command, file path, or flag, because the banner shows the title verbatim. Prose alone leaves the banner empty. Split it into the fewest substantial phases the task genuinely needs plus a final integration/whole-task phase; most tasks need one to three work phases. Each phase is a complete reviewable slice of behavior. Never split per file, per function, or per trivial step: over-splitting spends review turns instead of finishing the job. Add a phase only when a real review boundary, risky decision, or independent behavior separates the work. Complete exactly one phase per turn, and finish the whole phase in that turn rather than stopping early. Do not run tests, typecheck, lint, or builds per phase; write the tests the change needs, then run verification once in the final phase over the whole task. Exception: a phase whose own correctness is unclear may run the single narrowest check that resolves it. End every phase turn with phase completed, todo status, changed behavior/files, and remaining phases; do not start the next phase in the same turn. Server then wakes the paired Supervisor, which resumes you through ${FUSION_ADVICE_PROMPT_PREFIX}; a user message may also revise or resume the work. Final phase verifies the entire task against the original request and labels it ready for whole-task review. Supervisor is unreachable during your turn. Never spawn/use another Supervisor thread/subagent or attribute Supervisor decisions without ${FUSION_ADVICE_PROMPT_PREFIX}. Within the current phase, continue when straightforward or evidence is clear. For a concrete unresolved tradeoff, correctness risk, or design decision materially needing judgment, stop safely before the risky choice; final response states the exact question and why review is needed. Evaluate/follow Supervisor advice unless conflicting with user request or verified repo state.`;
64179
+ /**
64180
+ * The half of the protocol both roles share: how a pair message is written.
64181
+ *
64182
+ * The transport already carries the thread's compression mode - a Fusion child
64183
+ * inherits the composer's mode at creation, and `thread_advise` starts the
64184
+ * builder turn under the builder thread's stored mode - but neither role block
64185
+ * said that pair traffic is subject to it, so phase reports and advice were
64186
+ * written as if the setting applied only to user-facing answers.
64187
+ */
64188
+ const FUSION_PAIR_COMMUNICATION_INSTRUCTIONS = `Everything you send the other half of the pair obeys the thread's active response-compression mode, exactly as a user-facing answer does: phase reports, advice, reviews, questions, and handoffs. When the mode is off, write normal prose. Compression governs form only - never drop a requirement, a negation, a number or unit, a file, symbol, or command name, code, security or warning text, the evidence behind a claim, or an exact protocol heading or token in order to save words.`;
64189
+ const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder in an already-created native server pair. Server owns pairing and coordination. Do not inspect or invoke the Fusion skill, create/pair/rename threads, or announce/setup Fusion. Start the user's task directly. Before editing, create and maintain the phase list with your provider's step-tracking tool (Claude Code: TaskCreate for each phase, then TaskUpdate for status, or TodoWrite when that is the tool offered; Codex: update_plan), never the MCP task board tools - one entry per phase in order, exactly one in progress at a time, marked completed at each phase end - so phases render in the task banner. That list holds phase entries only for the whole task; keep step-level or per-file todos out of it. Name each phase in 3-6 words by its outcome, never by a command, file path, or flag, because the banner shows the title verbatim. Prose alone leaves the banner empty. Split it into the fewest substantial phases the task genuinely needs plus a final integration/whole-task phase; most tasks need one to three work phases. Each phase is a complete reviewable slice of behavior. Never split per file, per function, or per trivial step: over-splitting spends review turns instead of finishing the job. Add a phase only when a real review boundary, risky decision, or independent behavior separates the work. Complete exactly one phase per turn, and finish the whole phase in that turn rather than stopping early. Do not run tests, typecheck, lint, or builds per phase; write the tests the change needs, then run verification once in the final phase over the whole task. Exception: a phase whose own correctness is unclear may run the single narrowest check that resolves it. End every phase turn with phase completed, todo status, changed behavior/files, and remaining phases; do not start the next phase in the same turn. Server then wakes the paired Supervisor, which resumes you through ${FUSION_ADVICE_PROMPT_PREFIX}; a user message may also revise or resume the work. Final phase verifies the entire task against the original request and labels it ready for whole-task review. Supervisor is unreachable during your turn. Never spawn/use another Supervisor thread/subagent or attribute Supervisor decisions without ${FUSION_ADVICE_PROMPT_PREFIX}. Within the current phase, continue when straightforward or evidence is clear. For a concrete unresolved tradeoff, correctness risk, or design decision materially needing judgment, stop safely before the risky choice; final response states the exact question and why review is needed. Evaluate/follow Supervisor advice unless conflicting with user request or verified repo state. ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
63578
64190
  const FUSION_WATCHER_TOOL_INSTRUCTIONS = `Supervisor tools belong to the p4-code MCP server: thread_watch_review, thread_watch_events, thread_advise, and thread_gate_respond. If absent from the visible tool list, first use the available tool search/discovery facility to load those exact tools, including provider-prefixed names; absence from the initial list does not establish unavailability. If discovery or a call fails, report the exact missing capability or error and the need to restore the p4-code MCP connection. Do not offer manual relay, draft or implement the task yourself, or abandon the supervisor role as a workaround. For an actionable user requirement, read the relevant builder evidence and relay it through thread_advise; when a gate is open, answer through thread_gate_respond instead. Structure every actionable supervisor advice message with these Markdown headings, in order:
63579
64191
  ## Recommendation
63580
64192
  State the decision or correction in one sentence. For a phase review, say whether the phase is approved or needs changes.
@@ -63582,7 +64194,7 @@ State the decision or correction in one sentence. For a phase review, say whethe
63582
64194
  Give concise evidence, relevant file/line references, and any unresolved risk. Distinguish observed facts from assumptions; do not claim checks you did not run.
63583
64195
  ## Next step
63584
64196
  Give ordered, concrete actions for the builder, including the next phase and its completion condition. Preserve user requirements, constraints, and delivery authorization. Keep each section short; omit empty bullets and repeated status. Formatting does not authorize an otherwise unnecessary advice turn or replace an exact protocol response.`;
63585
- const FUSION_WATCHER_INSTRUCTIONS = `You are Fusion Supervisor (watcher) in an already-created native server pair. Server owns pairing and coordination and wakes you with ${FUSION_REVIEW_PROMPT_PREFIX} or ${FUSION_GATE_PROMPT_PREFIX} prompts at builder turn boundaries. A plain message outside such a wake may arrive after your conversational memory of the pair is gone; its [fusion-pair] metadata block is authoritative: the builder thread exists and is the counterpart thread id. Never report that no builder thread exists. For a new pair, the initial user request is yours: inspect the task and available project context, plan the work, then direct the first actionable phase to the idle builder through thread_advise. Include the original requirements, constraints, and authorized delivery scope in that direction. The builder has not received the initial prompt and must not start before your direction. Missing builder turn evidence is expected before that first direction; do not wait for it or implement the work yourself. Ask the user only when needed to resolve a blocking requirement. ${FUSION_WATCHER_TOOL_INSTRUCTIONS} To resume supervision, read builder evidence with thread_watch_review from lastReviewedImplementerSequence, capture its throughSequence on the first page and reuse that fixed bound while paging with nextAfterSequence until hasMore is false (including empty pages). Apply message append/replace operations by identity; recover truncated evidence through targeted raw thread_watch_events source ranges. Retain reviewed requirements and evidence for final review; recover missing context with targeted history reads rather than mandatory raw replay from zero, derive phase from artifacts (git log/status, PR, builder events, including its turn.plan.updated phase list), steer with thread_advise, and answer an open gate with thread_gate_respond. When a review or gate wake prompt specifies an explicit event range, that range wins over this metadata. Never poll or wait for the builder; deliver review or advice, then end the turn. Every thread_advise starts a builder turn whose completion wakes you again, so never advise a builder that is idle on an external wait or has nothing actionable; report the state in your own thread and end without advising.`;
64197
+ const FUSION_WATCHER_INSTRUCTIONS = `You are Fusion Supervisor (watcher) in an already-created native server pair. Server owns pairing and coordination and wakes you with ${FUSION_REVIEW_PROMPT_PREFIX} or ${FUSION_GATE_PROMPT_PREFIX} prompts at builder turn boundaries. A plain message outside such a wake may arrive after your conversational memory of the pair is gone; its [fusion-pair] metadata block is authoritative: the builder thread exists and is the counterpart thread id. Never report that no builder thread exists. For a new pair, the initial user request is yours, and its first turn is research, not relay. Research it: when the request names a ticket, read that ticket AND its comments, including replies and inline comments, and treat a later comment as newer intent than the description; read the code, docs, project instructions, and current state the request touches. Analyse what you found: root cause or the concrete design constraint, scope, what the user actually wants delivered, and which delivery steps they authorized. Only then direct the first actionable phase to the idle builder through thread_advise, stating the findings that make the direction actionable alongside the original requirements, constraints, and authorized delivery scope. Never echo the request back as its own direction, never hand over a plan you did not ground in evidence, and never send ${FUSION_NO_OBJECTION_TEXT} before the builder has received its first phase and produced a turn to review. The builder has not received the initial prompt and must not start before your direction. Missing builder turn evidence is expected before that first direction; do not wait for it or implement the work yourself. Ask the user only when needed to resolve a blocking requirement. ${FUSION_WATCHER_TOOL_INSTRUCTIONS} To resume supervision, read builder evidence with thread_watch_review from lastReviewedImplementerSequence, capture its throughSequence on the first page and reuse that fixed bound while paging with nextAfterSequence until hasMore is false (including empty pages). Apply message append/replace operations by identity; recover truncated evidence through targeted raw thread_watch_events source ranges. Retain reviewed requirements and evidence for final review; recover missing context with targeted history reads rather than mandatory raw replay from zero, derive phase from artifacts (git log/status, PR, builder events, including its turn.plan.updated phase list), steer with thread_advise, and answer an open gate with thread_gate_respond. When a review or gate wake prompt specifies an explicit event range, that range wins over this metadata. Never poll or wait for the builder; deliver review or advice, then end the turn. Every thread_advise starts a builder turn whose completion wakes you again, so never advise a builder that is idle on an external wait or has nothing actionable; report the state in your own thread and end without advising. ${FUSION_PAIR_COMMUNICATION_INSTRUCTIONS}`;
63586
64198
  /**
63587
64199
  * The one-line stand-in for the full block on a message whose session already
63588
64200
  * carries the role instructions.
@@ -83861,7 +84473,7 @@ const V2TurnStartParams__CollaborationMode = Schema$1.Struct({
83861
84473
  mode: V2TurnStartParams__ModeKind,
83862
84474
  settings: V2TurnStartParams__Settings
83863
84475
  }).annotate({ description: "Collaboration mode for a Codex session." });
83864
- Schema$1.Union([Schema$1.Literals(["explicitRequestOnly", "proactive"]), Schema$1.Struct({ custom: Schema$1.String }).annotate({ title: "CustomMultiAgentMode" })], { mode: "oneOf" }).annotate({ description: "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy." });
84476
+ const V2TurnStartParams__MultiAgentMode = Schema$1.Union([Schema$1.Literals(["explicitRequestOnly", "proactive"]), Schema$1.Struct({ custom: Schema$1.String }).annotate({ title: "CustomMultiAgentMode" })], { mode: "oneOf" }).annotate({ description: "Controls the effective multi-agent delegation instructions for a turn. `custom` means the configured mode hint defines the policy instead of a built-in policy." });
83865
84477
  Schema$1.Literals(["restricted", "enabled"]);
83866
84478
  Schema$1.Struct({
83867
84479
  cwd: V2TurnStartParams__LegacyAppPathString,
@@ -84842,7 +85454,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
84842
85454
  //#endregion
84843
85455
  //#region ../../packages/effect-codex-app-server/src/client.ts
84844
85456
  var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
84845
- const make$69 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
85457
+ const make$67 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
84846
85458
  const requestHandlers = /* @__PURE__ */ new Map();
84847
85459
  const notificationHandlers = /* @__PURE__ */ new Map();
84848
85460
  let unknownRequestHandler;
@@ -84909,7 +85521,7 @@ const make$69 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(f
84909
85521
  const layerChildProcess = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
84910
85522
  const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
84911
85523
  yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
84912
- return yield* make$69(makeChildStdio(handle), options, makeTerminationError(handle));
85524
+ return yield* make$67(makeChildStdio(handle), options, makeTerminationError(handle));
84913
85525
  });
84914
85526
  const resolveCodexLaunchArgs = (launchArgs, environment = process.env) => environment["P4CODE_CODEX_LAUNCH_ARGS"]?.trim() || launchArgs?.trim() || "";
84915
85527
  const codexLaunchArgv = (launchArgs) => tokenizeCliArgs(launchArgs);
@@ -85205,7 +85817,7 @@ function buildCodexInitializeParams() {
85205
85817
  return {
85206
85818
  clientInfo: {
85207
85819
  name: "p4code_desktop",
85208
- title: "P4Code Desktop",
85820
+ title: "P4 Code Desktop",
85209
85821
  version: version$1
85210
85822
  },
85211
85823
  capabilities: { experimentalApi: true }
@@ -85237,7 +85849,7 @@ const probeCodexAppServerProvider = Effect.fn("probeCodexAppServerProvider")(fun
85237
85849
  const initialize = yield* client.request("initialize", {
85238
85850
  clientInfo: {
85239
85851
  name: "p4code_desktop",
85240
- title: "P4Code Desktop",
85852
+ title: "P4 Code Desktop",
85241
85853
  version: "0.1.0"
85242
85854
  },
85243
85855
  capabilities: { experimentalApi: true }
@@ -85294,7 +85906,7 @@ const makePendingCodexProvider = (codexSettings) => Effect.gen(function* () {
85294
85906
  version: null,
85295
85907
  status: "warning",
85296
85908
  auth: { status: "unknown" },
85297
- message: "Codex is disabled in P4Code settings."
85909
+ message: "Codex is disabled in P4 Code settings."
85298
85910
  }
85299
85911
  });
85300
85912
  return buildServerProvider({
@@ -85350,7 +85962,7 @@ const checkCodexProviderStatus = Effect.fn("checkCodexProviderStatus")(function*
85350
85962
  version: null,
85351
85963
  status: "warning",
85352
85964
  auth: { status: "unknown" },
85353
- message: "Codex is disabled in P4Code settings."
85965
+ message: "Codex is disabled in P4 Code settings."
85354
85966
  }
85355
85967
  });
85356
85968
  const probeResult = yield* probe({
@@ -86110,7 +86722,10 @@ const CodexResumeCursorSchema = Schema$1.Struct({ threadId: Schema$1.String });
86110
86722
  const CodexUserInputAnswerObject = Schema$1.Struct({ answers: Schema$1.Array(Schema$1.String) });
86111
86723
  const isCodexResumeCursorSchema$1 = Schema$1.is(CodexResumeCursorSchema);
86112
86724
  const isCodexUserInputAnswerObject = Schema$1.is(CodexUserInputAnswerObject);
86113
- const CodexTurnStartParamsWithCollaborationMode = V2TurnStartParams.pipe(Schema$1.fieldsAssign({ collaborationMode: Schema$1.optionalKey(V2TurnStartParams__CollaborationMode) }));
86725
+ const CodexTurnStartParamsWithCollaborationMode = V2TurnStartParams.pipe(Schema$1.fieldsAssign({
86726
+ collaborationMode: Schema$1.optionalKey(V2TurnStartParams__CollaborationMode),
86727
+ multiAgentMode: Schema$1.optionalKey(V2TurnStartParams__MultiAgentMode)
86728
+ }));
86114
86729
  const decodeCodexTurnStartParamsWithCollaborationMode = Schema$1.decodeUnknownEffect(CodexTurnStartParamsWithCollaborationMode);
86115
86730
  var CodexSessionRuntimePendingApprovalNotFoundError = class extends Schema$1.TaggedErrorClass()("CodexSessionRuntimePendingApprovalNotFoundError", { requestId: Schema$1.String }) {
86116
86731
  get message() {
@@ -86236,6 +86851,7 @@ function buildTurnStartParams(input) {
86236
86851
  ...input.model ? { model: input.model } : {},
86237
86852
  ...input.serviceTier ? { serviceTier: input.serviceTier } : {},
86238
86853
  ...input.effort ? { effort: input.effort } : {},
86854
+ ...input.unpromptedSubagents !== void 0 ? { multiAgentMode: input.unpromptedSubagents ? "proactive" : "explicitRequestOnly" } : {},
86239
86855
  ...collaborationMode ? { collaborationMode } : {}
86240
86856
  }).pipe(compressRulesetUndeliverable ? Effect.tap(() => Effect.logWarning("codex.turn.compress-ruleset-undeliverable", {
86241
86857
  threadId: input.threadId,
@@ -86811,7 +87427,8 @@ const makeCodexSessionRuntime = (options) => Effect.gen(function* () {
86811
87427
  ...input.effort ? { effort: input.effort } : {},
86812
87428
  ...input.interactionMode ? { interactionMode: input.interactionMode } : {},
86813
87429
  ...input.compressMode ? { compressMode: input.compressMode } : {},
86814
- ...options.guardrailPrompts ? { guardrailPrompts: options.guardrailPrompts } : {}
87430
+ ...options.guardrailPrompts ? { guardrailPrompts: options.guardrailPrompts } : {},
87431
+ ...input.unpromptedSubagents !== void 0 ? { unpromptedSubagents: input.unpromptedSubagents } : {}
86815
87432
  });
86816
87433
  const { collaborationMode: attachedCollaborationMode, ...paramsWithoutCollaboration } = params;
86817
87434
  const lastCollaborationMode = yield* Ref.get(lastCollaborationModeRef);
@@ -87992,6 +88609,7 @@ const makeCodexAdapter = Effect.fn("makeCodexAdapter")(function* (codexConfig, o
87992
88609
  ...input.interactionMode !== void 0 ? { interactionMode: input.interactionMode } : {},
87993
88610
  ...input.compressMode !== void 0 ? { compressMode: input.compressMode } : {},
87994
88611
  ...input.fusionRole !== void 0 ? { fusionRole: input.fusionRole } : {},
88612
+ ...input.unpromptedSubagents !== void 0 ? { unpromptedSubagents: input.unpromptedSubagents } : {},
87995
88613
  ...codexAttachments.length > 0 ? { attachments: codexAttachments } : {}
87996
88614
  }).pipe(Effect.mapError((cause) => mapCodexRuntimeError(input.threadId, "turn/start", cause)));
87997
88615
  });
@@ -88562,7 +89180,7 @@ const CURSOR_PARAMETERIZED_MODEL_PICKER_MIN_VERSION_DATE = 20260408;
88562
89180
  const CURSOR_CLI_INSTALLATION_DOCS_URL = "https://cursor.com/docs/cli/installation";
88563
89181
  const CURSOR_ACP_MODEL_DISCOVERY_FAILED_MESSAGE = [
88564
89182
  "Cursor ACP model discovery failed.",
88565
- "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart P4Code, and try again.",
89183
+ "Cursor CLI setup may be incomplete; install or enable the Cursor CLI, restart P4 Code, and try again.",
88566
89184
  `See ${CURSOR_CLI_INSTALLATION_DOCS_URL}.`,
88567
89185
  "Check server logs for ACP details."
88568
89186
  ].join(" ");
@@ -88581,7 +89199,7 @@ function buildInitialCursorProviderSnapshot(cursorSettings) {
88581
89199
  version: null,
88582
89200
  status: "warning",
88583
89201
  auth: { status: "unknown" },
88584
- message: "Cursor is disabled in P4Code settings."
89202
+ message: "Cursor is disabled in P4 Code settings."
88585
89203
  }
88586
89204
  });
88587
89205
  return buildServerProvider({
@@ -88747,7 +89365,7 @@ function buildCursorDiscoveredModelsFromAvailableModelsResponse(response) {
88747
89365
  }
88748
89366
  const makeCursorAcpProbeRuntime = (cursorSettings, environment) => Effect.gen(function* () {
88749
89367
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
88750
- const acpContext = yield* Layer.build(layer$62({
89368
+ const acpContext = yield* Layer.build(layer$60({
88751
89369
  spawn: {
88752
89370
  command: cursorSettings.binaryPath,
88753
89371
  args: [...cursorSettings.apiEndpoint ? ["-e", cursorSettings.apiEndpoint] : [], "acp"],
@@ -88859,7 +89477,7 @@ function joinProviderMessages(...messages) {
88859
89477
  function buildCursorCliCommandMissingMessage(binaryPath) {
88860
89478
  return [
88861
89479
  `Cursor CLI command \`${binaryPath}\` was not found.`,
88862
- `Install or enable the Cursor CLI, make sure \`${binaryPath}\` is on PATH, then restart P4Code.`,
89480
+ `Install or enable the Cursor CLI, make sure \`${binaryPath}\` is on PATH, then restart P4 Code.`,
88863
89481
  `See ${CURSOR_CLI_INSTALLATION_DOCS_URL}.`
88864
89482
  ].join(" ");
88865
89483
  }
@@ -89099,7 +89717,7 @@ const checkCursorProviderStatus = Effect.fn("checkCursorProviderStatus")(functio
89099
89717
  version: null,
89100
89718
  status: "warning",
89101
89719
  auth: { status: "unknown" },
89102
- message: "Cursor is disabled in P4Code settings."
89720
+ message: "Cursor is disabled in P4 Code settings."
89103
89721
  }
89104
89722
  });
89105
89723
  const aboutProbe = yield* runCursorAboutCommand(cursorSettings, environment).pipe(Effect.timeoutOption(ABOUT_TIMEOUT_MS), Effect.result);
@@ -89197,7 +89815,7 @@ function buildCursorAcpSpawnInput(cursorSettings, cwd, environment) {
89197
89815
  };
89198
89816
  }
89199
89817
  const makeCursorAcpRuntime = (input) => Effect.gen(function* () {
89200
- const acpContext = yield* Layer.build(layer$62({
89818
+ const acpContext = yield* Layer.build(layer$60({
89201
89819
  ...input,
89202
89820
  spawn: buildCursorAcpSpawnInput(input.cursorSettings, input.cwd, input.environment),
89203
89821
  authMethodId: "cursor_login",
@@ -90390,7 +91008,7 @@ function resolveGrokAuthMethodId(environment) {
90390
91008
  return environment?.[GROK_API_KEY_ENV]?.trim() ? GROK_AUTH_METHOD_API_KEY : GROK_AUTH_METHOD_CACHED_TOKEN;
90391
91009
  }
90392
91010
  const makeGrokAcpRuntime = (input) => Effect.gen(function* () {
90393
- const acpContext = yield* Layer.build(layer$62({
91011
+ const acpContext = yield* Layer.build(layer$60({
90394
91012
  ...input,
90395
91013
  spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd, input.environment),
90396
91014
  authMethodId: resolveGrokAuthMethodId(input.environment)
@@ -91457,7 +92075,7 @@ function buildInitialGrokProviderSnapshot(grokSettings) {
91457
92075
  version: null,
91458
92076
  status: "warning",
91459
92077
  auth: { status: "unknown" },
91460
- message: "Grok is disabled in P4Code settings."
92078
+ message: "Grok is disabled in P4 Code settings."
91461
92079
  }
91462
92080
  });
91463
92081
  return buildServerProvider({
@@ -91526,7 +92144,7 @@ const checkGrokProviderStatus = Effect.fn("checkGrokProviderStatus")(function* (
91526
92144
  version: null,
91527
92145
  status: "warning",
91528
92146
  auth: { status: "unknown" },
91529
- message: "Grok is disabled in P4Code settings."
92147
+ message: "Grok is disabled in P4 Code settings."
91530
92148
  }
91531
92149
  });
91532
92150
  const versionResult = yield* runGrokVersionCommand(grokSettings, environment).pipe(Effect.timeoutOption(VERSION_PROBE_TIMEOUT_MS$1), Effect.result);
@@ -93186,7 +93804,7 @@ function buildInitialMuseProviderSnapshot(museSettings) {
93186
93804
  version: null,
93187
93805
  status: "warning",
93188
93806
  auth: { status: "unknown" },
93189
- message: "Muse Code is disabled in P4Code settings."
93807
+ message: "Muse Code is disabled in P4 Code settings."
93190
93808
  }
93191
93809
  });
93192
93810
  });
@@ -93212,7 +93830,7 @@ const checkMuseProviderStatus = Effect.fn("checkMuseProviderStatus")(function* (
93212
93830
  version: null,
93213
93831
  status: "warning",
93214
93832
  auth: { status: "unknown" },
93215
- message: "Muse Code is disabled in P4Code settings."
93833
+ message: "Muse Code is disabled in P4 Code settings."
93216
93834
  }
93217
93835
  });
93218
93836
  const versionResult = yield* runMuseVersionCommand(museSettings, environment).pipe(Effect.timeoutOption(VERSION_PROBE_TIMEOUT_MS), Effect.result);
@@ -94024,7 +94642,7 @@ const makeOpenCodeTextGeneration = Effect.fn("makeOpenCodeTextGeneration")(funct
94024
94642
  });
94025
94643
  const session = yield* Effect.tryPromise({
94026
94644
  try: () => client.session.create({
94027
- title: `P4Code ${input.operation}`,
94645
+ title: `P4 Code ${input.operation}`,
94028
94646
  permission: [{
94029
94647
  permission: "*",
94030
94648
  pattern: "*",
@@ -95410,7 +96028,7 @@ const makePendingOpenCodeProvider = (openCodeSettings) => Effect.gen(function* (
95410
96028
  version: null,
95411
96029
  status: "warning",
95412
96030
  auth: { status: "unknown" },
95413
- message: openCodeSettings.serverUrl.trim().length > 0 ? "OpenCode is disabled in P4Code settings. A server URL is configured." : "OpenCode is disabled in P4Code settings."
96031
+ message: openCodeSettings.serverUrl.trim().length > 0 ? "OpenCode is disabled in P4 Code settings. A server URL is configured." : "OpenCode is disabled in P4 Code settings."
95414
96032
  }
95415
96033
  });
95416
96034
  return buildServerProvider({
@@ -95463,7 +96081,7 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
95463
96081
  version: null,
95464
96082
  status: "warning",
95465
96083
  auth: { status: "unknown" },
95466
- message: isExternalServer ? "OpenCode is disabled in P4Code settings. A server URL is configured." : "OpenCode is disabled in P4Code settings."
96084
+ message: isExternalServer ? "OpenCode is disabled in P4 Code settings. A server URL is configured." : "OpenCode is disabled in P4 Code settings."
95467
96085
  }
95468
96086
  });
95469
96087
  let version = null;
@@ -95478,7 +96096,7 @@ const checkOpenCodeProviderStatus = Effect.fn("checkOpenCodeProviderStatus")(fun
95478
96096
  }))));
95479
96097
  if (versionExit._tag === "Failure") return fallback(Cause.squash(versionExit.cause));
95480
96098
  version = parseGenericCliVersion(versionExit.value.stdout) ?? null;
95481
- if (!version) return fallback(/* @__PURE__ */ new Error(`Unable to determine OpenCode version from \`opencode --version\` output. P4Code requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`), null);
96099
+ if (!version) return fallback(/* @__PURE__ */ new Error(`Unable to determine OpenCode version from \`opencode --version\` output. P4 Code requires OpenCode v${MINIMUM_OPENCODE_VERSION} or newer.`), null);
95482
96100
  if (compareSemverVersions(version, MINIMUM_OPENCODE_VERSION) < 0) return buildServerProvider({
95483
96101
  presentation: OPENCODE_PRESENTATION,
95484
96102
  enabled: openCodeSettings.enabled,
@@ -96131,7 +96749,7 @@ const makeProviderInstallation = Effect.fn("makeProviderInstallation")(function*
96131
96749
  })))).binaryPath) return yield* new ProviderSetupError({
96132
96750
  instanceId,
96133
96751
  operation,
96134
- detail: "This instance uses a custom executable. Clear its binary path to manage installation in P4Code."
96752
+ detail: "This instance uses a custom executable. Clear its binary path to manage installation in P4 Code."
96135
96753
  });
96136
96754
  });
96137
96755
  const failure = (instanceId) => (error) => new ProviderSetupError({
@@ -96169,7 +96787,7 @@ const makeProviderInstallation = Effect.fn("makeProviderInstallation")(function*
96169
96787
  });
96170
96788
  //#endregion
96171
96789
  //#region src/usage/usageSourceHttp.ts
96172
- const MAX_RESPONSE_BYTES$2 = 1024 * 1024;
96790
+ const MAX_RESPONSE_BYTES$1 = 1024 * 1024;
96173
96791
  const LOOPBACK_HOSTS$1 = /* @__PURE__ */ new Set([
96174
96792
  "localhost",
96175
96793
  "127.0.0.1",
@@ -96202,7 +96820,7 @@ async function readManagementJson(config, path, body, signal) {
96202
96820
  const chunk = await reader.read();
96203
96821
  if (chunk.done) break;
96204
96822
  total += chunk.value.byteLength;
96205
- if (total > MAX_RESPONSE_BYTES$2) throw new Error("Usage source response too large");
96823
+ if (total > MAX_RESPONSE_BYTES$1) throw new Error("Usage source response too large");
96206
96824
  chunks.push(chunk.value);
96207
96825
  }
96208
96826
  return JSON.parse(Buffer.concat(chunks).toString("utf8"));
@@ -96439,8 +97057,8 @@ const makeWithReader = (api) => Effect.gen(function* () {
96439
97057
  }))
96440
97058
  };
96441
97059
  });
96442
- const make$68 = makeCliproxyApi.pipe(Effect.flatMap(makeWithReader));
96443
- const layer$59 = Layer.effect(UsageLimitSources, make$68);
97060
+ const make$66 = makeCliproxyApi.pipe(Effect.flatMap(makeWithReader));
97061
+ const layer$57 = Layer.effect(UsageLimitSources, make$66);
96444
97062
  //#endregion
96445
97063
  //#region src/resourceTelemetry/HostResources.ts
96446
97064
  const CPU_SAMPLE_INTERVAL = "200 millis";
@@ -96475,7 +97093,7 @@ function darwinAvailableMemory(output) {
96475
97093
  const available = (Number(free) + Number(inactive) + Number(speculative)) * Number(pageSize);
96476
97094
  return Number.isSafeInteger(available) && Number(pageSize) > 0 ? available : null;
96477
97095
  }
96478
- const make$67 = Effect.fn("makeHostResources")(function* () {
97096
+ const make$65 = Effect.fn("makeHostResources")(function* () {
96479
97097
  const fs = yield* FileSystem.FileSystem;
96480
97098
  const platform = yield* HostProcessPlatform;
96481
97099
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
@@ -96509,7 +97127,7 @@ const make$67 = Effect.fn("makeHostResources")(function* () {
96509
97127
  });
96510
97128
  return HostResources.of({ read: Cache.get(cache, "host") });
96511
97129
  });
96512
- const layer$58 = Layer.effect(HostResources, make$67());
97130
+ const layer$56 = Layer.effect(HostResources, make$65());
96513
97131
  //#endregion
96514
97132
  //#region src/resourceTelemetry/DesktopTelemetryReceiver.ts
96515
97133
  const INITIAL_SAMPLE_DEADLINE_MS = 9e4;
@@ -96644,7 +97262,7 @@ function requireDesktopTelemetryWriteProgress(fd, remainingBytes, written) {
96644
97262
  }));
96645
97263
  }
96646
97264
  /** @public Service construction is part of the canonical Effect module API. */
96647
- const make$66 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
97265
+ const make$64 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
96648
97266
  const serverConfig = yield* ServerConfig$1;
96649
97267
  const hasDescriptors = serverConfig.mode === "desktop" && serverConfig.desktopTelemetryFd === 4 && serverConfig.desktopTelemetryControlFd === 5;
96650
97268
  const config = {
@@ -96801,7 +97419,7 @@ const make$66 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(fun
96801
97419
  setDiagnosticsDemand
96802
97420
  });
96803
97421
  });
96804
- const layer$57 = Layer.effect(DesktopTelemetryReceiver, make$66());
97422
+ const layer$55 = Layer.effect(DesktopTelemetryReceiver, make$64());
96805
97423
  //#endregion
96806
97424
  //#region src/resourceTelemetry/Model.ts
96807
97425
  const MAX_DELTA_INTERVAL_MS = 3e4;
@@ -97226,7 +97844,7 @@ function resourceMonitorRustTarget(platform, architecture, linuxLibc) {
97226
97844
  }
97227
97845
  if (platform === "win32") return architecture === "arm64" ? "aarch64-pc-windows-msvc" : architecture === "x64" ? "x86_64-pc-windows-msvc" : void 0;
97228
97846
  }
97229
- const make$65 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(function* () {
97847
+ const make$63 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(function* () {
97230
97848
  const fileSystem = yield* FileSystem.FileSystem;
97231
97849
  const path = yield* Path$1.Path;
97232
97850
  const platform = yield* HostProcessPlatform;
@@ -97272,7 +97890,7 @@ const make$65 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(functi
97272
97890
  });
97273
97891
  return ResourceMonitorBinary.of({ resolve });
97274
97892
  });
97275
- const layer$56 = Layer.effect(ResourceMonitorBinary, make$65());
97893
+ const layer$54 = Layer.effect(ResourceMonitorBinary, make$63());
97276
97894
  //#endregion
97277
97895
  //#region src/resourceTelemetry/NativeTelemetryClient.ts
97278
97896
  const SAMPLE_INTERVAL_MS$1 = 1e3;
@@ -97422,7 +98040,7 @@ function canCommandNativeTelemetrySidecar(status, hasHandle) {
97422
98040
  return hasHandle && (status === "healthy" || status === "degraded");
97423
98041
  }
97424
98042
  /** @public Service construction is part of the canonical Effect module API. */
97425
- const make$64 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
98043
+ const make$62 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
97426
98044
  const binary = yield* ResourceMonitorBinary;
97427
98045
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
97428
98046
  const crypto = yield* Crypto.Crypto;
@@ -97833,7 +98451,7 @@ const make$64 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(functi
97833
98451
  })
97834
98452
  });
97835
98453
  });
97836
- const layer$55 = Layer.effect(NativeTelemetryClient, make$64());
98454
+ const layer$53 = Layer.effect(NativeTelemetryClient, make$62());
97837
98455
  //#endregion
97838
98456
  //#region src/resourceTelemetry/ResourceAttribution.ts
97839
98457
  var ResourceAttribution = class extends Context.Service()("@p4code/cli/resourceTelemetry/ResourceAttribution") {};
@@ -97845,7 +98463,7 @@ function nonNegativeInteger(value, fallback) {
97845
98463
  if (!Number.isFinite(value)) return 0;
97846
98464
  return Math.max(0, Math.round(value));
97847
98465
  }
97848
- const make$63 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function* () {
98466
+ const make$61 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function* () {
97849
98467
  const entries = yield* Ref.make(/* @__PURE__ */ new Map());
97850
98468
  const record = (input) => Ref.update(entries, (current) => {
97851
98469
  const next = new Map(current);
@@ -97871,7 +98489,7 @@ const make$63 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function
97871
98489
  })
97872
98490
  });
97873
98491
  });
97874
- const layer$54 = Layer.effect(ResourceAttribution, make$63());
98492
+ const layer$52 = Layer.effect(ResourceAttribution, make$61());
97875
98493
  //#endregion
97876
98494
  //#region src/resourceTelemetry/ResourceTelemetryHistory.ts
97877
98495
  const MAX_HISTORY_WINDOW_MS = 60 * 6e4;
@@ -98094,7 +98712,7 @@ function buildHealth(input) {
98094
98712
  };
98095
98713
  }
98096
98714
  /** @public Service construction is part of the canonical Effect module API. */
98097
- const make$62 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
98715
+ const make$60 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
98098
98716
  const nativeClient = yield* NativeTelemetryClient;
98099
98717
  const desktopReceiver = yield* DesktopTelemetryReceiver;
98100
98718
  const attribution = yield* ResourceAttribution;
@@ -98346,7 +98964,7 @@ const make$62 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function*
98346
98964
  })))
98347
98965
  });
98348
98966
  });
98349
- const layer$53 = Layer.effect(ResourceTelemetry, make$62());
98967
+ const layer$51 = Layer.effect(ResourceTelemetry, make$60());
98350
98968
  //#endregion
98351
98969
  //#region src/device/DeviceInspection.ts
98352
98970
  const READ_TIMEOUT_MS = 1e4;
@@ -101501,7 +102119,7 @@ const classifyNonZeroExit = (command, stderr) => {
101501
102119
  if (command === "gh" && (normalized.includes("could not resolve to a pullrequest") || normalized.includes("repository.pullrequest") || normalized.includes("no pull requests found for branch") || normalized.includes("pull request not found")) || command === "glab" && (normalized.includes("merge request not found") || normalized.includes("not found") || normalized.includes("404")) || command === "az" && normalized.includes("pull request") && (normalized.includes("not found") || normalized.includes("does not exist"))) return "not-found";
101502
102120
  return "command-failed";
101503
102121
  };
101504
- const make$61 = Effect.gen(function* () {
102122
+ const make$59 = Effect.gen(function* () {
101505
102123
  const processRunner = yield* ProcessRunner;
101506
102124
  const run = Effect.fn("VcsProcess.run")(function* (input) {
101507
102125
  const baseError = {
@@ -101560,7 +102178,7 @@ const make$61 = Effect.gen(function* () {
101560
102178
  });
101561
102179
  return VcsProcess.of({ run });
101562
102180
  });
101563
- const layer$52 = Layer.effect(VcsProcess, make$61).pipe(Layer.provide(layer$81));
102181
+ const layer$50 = Layer.effect(VcsProcess, make$59).pipe(Layer.provide(layer$81));
101564
102182
  //#endregion
101565
102183
  //#region src/vcs/VcsDriver.ts
101566
102184
  var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
@@ -102011,12 +102629,12 @@ const makeVcsDriver = Effect.gen(function* () {
102011
102629
  const driver = yield* makeVcsDriverShape();
102012
102630
  return VcsDriver.of(driver);
102013
102631
  });
102014
- const make$60 = Effect.gen(function* () {
102632
+ const make$58 = Effect.gen(function* () {
102015
102633
  const git = yield* makeGitVcsDriverCore();
102016
102634
  return GitVcsDriver.of(git);
102017
102635
  });
102018
102636
  Layer.effect(VcsDriver, makeVcsDriver);
102019
- const layer$51 = Layer.effect(GitVcsDriver, make$60);
102637
+ const layer$49 = Layer.effect(GitVcsDriver, make$58);
102020
102638
  //#endregion
102021
102639
  //#region src/vcs/VcsProjectConfig.ts
102022
102640
  const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
@@ -102048,7 +102666,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
102048
102666
  configPath: error.configPath,
102049
102667
  errorTag: error._tag
102050
102668
  }));
102051
- const make$59 = Effect.gen(function* () {
102669
+ const make$57 = Effect.gen(function* () {
102052
102670
  const fileSystem = yield* FileSystem.FileSystem;
102053
102671
  const path = yield* Path$1.Path;
102054
102672
  const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
@@ -102089,7 +102707,7 @@ const make$59 = Effect.gen(function* () {
102089
102707
  });
102090
102708
  return VcsProjectConfig.of({ resolveKind });
102091
102709
  });
102092
- const layer$50 = Layer.effect(VcsProjectConfig, make$59);
102710
+ const layer$48 = Layer.effect(VcsProjectConfig, make$57);
102093
102711
  //#endregion
102094
102712
  //#region src/vcs/VcsDriverRegistry.ts
102095
102713
  const DETECTION_CACHE_CAPACITY = 2048;
@@ -102109,7 +102727,7 @@ function parseDetectionCacheKey(key) {
102109
102727
  cwd: key.slice(separatorIndex + 1)
102110
102728
  };
102111
102729
  }
102112
- const make$58 = Effect.gen(function* () {
102730
+ const make$56 = Effect.gen(function* () {
102113
102731
  const projectConfig = yield* VcsProjectConfig;
102114
102732
  const git = yield* makeVcsDriver;
102115
102733
  const drivers = { git };
@@ -102166,7 +102784,7 @@ const make$58 = Effect.gen(function* () {
102166
102784
  resolve
102167
102785
  });
102168
102786
  });
102169
- const layer$49 = Layer.effect(VcsDriverRegistry, make$58).pipe(Layer.provide(layer$50));
102787
+ const layer$47 = Layer.effect(VcsDriverRegistry, make$56).pipe(Layer.provide(layer$48));
102170
102788
  //#endregion
102171
102789
  //#region src/checkpointing/CheckpointStore.ts
102172
102790
  /**
@@ -102186,7 +102804,7 @@ const layer$49 = Layer.effect(VcsDriverRegistry, make$58).pipe(Layer.provide(lay
102186
102804
  */
102187
102805
  /** Service tag for checkpoint persistence and restore operations. */
102188
102806
  var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
102189
- const make$57 = Effect.gen(function* () {
102807
+ const make$55 = Effect.gen(function* () {
102190
102808
  const vcsRegistry = yield* VcsDriverRegistry;
102191
102809
  const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
102192
102810
  const handle = yield* vcsRegistry.resolve({ cwd });
@@ -102225,7 +102843,7 @@ const make$57 = Effect.gen(function* () {
102225
102843
  deleteCheckpointRefs
102226
102844
  });
102227
102845
  });
102228
- const layer$48 = Layer.effect(CheckpointStore, make$57);
102846
+ const layer$46 = Layer.effect(CheckpointStore, make$55);
102229
102847
  //#endregion
102230
102848
  //#region src/checkpointing/CheckpointDiffQuery.ts
102231
102849
  /**
@@ -102247,7 +102865,7 @@ function buildTurnDiffResult(input, diff) {
102247
102865
  diff
102248
102866
  };
102249
102867
  }
102250
- const make$56 = Effect.gen(function* () {
102868
+ const make$54 = Effect.gen(function* () {
102251
102869
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
102252
102870
  const checkpointStore = yield* CheckpointStore;
102253
102871
  const threadActivities = yield* ProjectionThreadActivityRepository;
@@ -102418,7 +103036,7 @@ const make$56 = Effect.gen(function* () {
102418
103036
  getFullThreadDiff
102419
103037
  });
102420
103038
  });
102421
- const layer$47 = Layer.effect(CheckpointDiffQuery, make$56);
103039
+ const layer$45 = Layer.effect(CheckpointDiffQuery, make$54);
102422
103040
  //#endregion
102423
103041
  //#region src/orchestration/ThreadLiveEventCoalescer.ts
102424
103042
  const COALESCE_WINDOW = Duration.millis(50);
@@ -102963,7 +103581,7 @@ const serversEqual = (left, right) => {
102963
103581
  }
102964
103582
  return true;
102965
103583
  };
102966
- const make$55 = Effect.gen(function* PortDiscoveryMake() {
103584
+ const make$53 = Effect.gen(function* PortDiscoveryMake() {
102967
103585
  const net = yield* NetService;
102968
103586
  const processRunner = yield* ProcessRunner;
102969
103587
  const hostPlatform = yield* HostProcessPlatform;
@@ -103114,7 +103732,7 @@ const make$55 = Effect.gen(function* PortDiscoveryMake() {
103114
103732
  unregisterTerminal
103115
103733
  });
103116
103734
  }).pipe(Effect.withSpan("PortDiscovery.make"));
103117
- const layer$46 = Layer.effect(PortDiscovery, make$55);
103735
+ const layer$44 = Layer.effect(PortDiscovery, make$53);
103118
103736
  //#endregion
103119
103737
  //#region src/terminal/Manager.ts
103120
103738
  /**
@@ -103792,7 +104410,7 @@ function normalizedRuntimeEnv(env) {
103792
104410
  if (entries.length === 0) return null;
103793
104411
  return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
103794
104412
  }
103795
- const make$54 = Effect.fn("TerminalManager.make")(function* () {
104413
+ const make$52 = Effect.fn("TerminalManager.make")(function* () {
103796
104414
  const { terminalLogsDir } = yield* ServerConfig$1;
103797
104415
  const ptyAdapter = yield* PtyAdapter;
103798
104416
  const portDiscovery = yield* PortDiscovery;
@@ -104754,7 +105372,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
104754
105372
  subscribeMetadata
104755
105373
  });
104756
105374
  });
104757
- const layer$45 = Layer.effect(TerminalManager, make$54()).pipe(Layer.provide(layer$81));
105375
+ const layer$43 = Layer.effect(TerminalManager, make$52()).pipe(Layer.provide(layer$81));
104758
105376
  //#endregion
104759
105377
  //#region src/project/ProjectSetupScriptRunner.ts
104760
105378
  var ProjectSetupScriptOperationError = class extends Schema$1.TaggedErrorClass()("ProjectSetupScriptOperationError", {
@@ -104786,7 +105404,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
104786
105404
  };
104787
105405
  Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
104788
105406
  var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
104789
- const make$53 = Effect.gen(function* () {
105407
+ const make$51 = Effect.gen(function* () {
104790
105408
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
104791
105409
  const terminalManager = yield* TerminalManager;
104792
105410
  const settingsService = yield* Effect.serviceOption(ServerSettingsService);
@@ -104849,7 +105467,7 @@ const make$53 = Effect.gen(function* () {
104849
105467
  });
104850
105468
  return ProjectSetupScriptRunner.of({ runForThread });
104851
105469
  });
104852
- const layer$44 = Layer.effect(ProjectSetupScriptRunner, make$53);
105470
+ const layer$42 = Layer.effect(ProjectSetupScriptRunner, make$51);
104853
105471
  //#endregion
104854
105472
  //#region src/sourceControl/azureDevOpsPullRequests.ts
104855
105473
  const AzureDevOpsPullRequestSchema = Schema$1.Struct({
@@ -105177,7 +105795,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
105177
105795
  cause
105178
105796
  })));
105179
105797
  }
105180
- const make$52 = Effect.gen(function* () {
105798
+ const make$50 = Effect.gen(function* () {
105181
105799
  const process = yield* VcsProcess;
105182
105800
  const execute = (input) => process.run({
105183
105801
  operation: "AzureDevOpsCli.execute",
@@ -105319,7 +105937,7 @@ const make$52 = Effect.gen(function* () {
105319
105937
  }).pipe(Effect.asVoid)
105320
105938
  });
105321
105939
  });
105322
- const layer$43 = Layer.effect(AzureDevOpsCli, make$52);
105940
+ const layer$41 = Layer.effect(AzureDevOpsCli, make$50);
105323
105941
  //#endregion
105324
105942
  //#region src/sourceControl/SourceControlProviderDiscovery.ts
105325
105943
  function firstNonEmptyLine(text) {
@@ -105523,7 +106141,7 @@ function toChangeRequest$5(summary) {
105523
106141
  isCrossRepository: false
105524
106142
  };
105525
106143
  }
105526
- const make$51 = Effect.gen(function* () {
106144
+ const make$49 = Effect.gen(function* () {
105527
106145
  const azure = yield* AzureDevOpsCli;
105528
106146
  return SourceControlProvider.of({
105529
106147
  kind: "azure-devops",
@@ -105616,7 +106234,7 @@ const make$51 = Effect.gen(function* () {
105616
106234
  })))
105617
106235
  });
105618
106236
  });
105619
- Layer.effect(SourceControlProvider, make$51);
106237
+ Layer.effect(SourceControlProvider, make$49);
105620
106238
  //#endregion
105621
106239
  //#region src/sourceControl/bitbucketPullRequests.ts
105622
106240
  const BitbucketRepositoryRefSchema = Schema$1.Struct({
@@ -105993,7 +106611,7 @@ function responseError(operation, response) {
105993
106611
  responseBodyLength: collected.text.length
105994
106612
  }))));
105995
106613
  }
105996
- const make$50 = Effect.gen(function* () {
106614
+ const make$48 = Effect.gen(function* () {
105997
106615
  const config = yield* BitbucketApiEnvConfig;
105998
106616
  const httpClient = yield* HttpClient.HttpClient;
105999
106617
  const fileSystem = yield* FileSystem.FileSystem;
@@ -106209,7 +106827,7 @@ const make$50 = Effect.gen(function* () {
106209
106827
  })))
106210
106828
  });
106211
106829
  });
106212
- const layer$41 = Layer.effect(BitbucketApi, make$50);
106830
+ const layer$39 = Layer.effect(BitbucketApi, make$48);
106213
106831
  //#endregion
106214
106832
  //#region src/sourceControl/BitbucketSourceControlProvider.ts
106215
106833
  function toChangeRequest$4(summary) {
@@ -106227,7 +106845,7 @@ function toChangeRequest$4(summary) {
106227
106845
  ...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
106228
106846
  };
106229
106847
  }
106230
- const make$49 = Effect.gen(function* () {
106848
+ const make$47 = Effect.gen(function* () {
106231
106849
  const bitbucket = yield* BitbucketApi;
106232
106850
  return SourceControlProvider.of({
106233
106851
  kind: "bitbucket",
@@ -106318,7 +106936,7 @@ const make$49 = Effect.gen(function* () {
106318
106936
  })))
106319
106937
  });
106320
106938
  });
106321
- Layer.effect(SourceControlProvider, make$49);
106939
+ Layer.effect(SourceControlProvider, make$47);
106322
106940
  const makeDiscovery = Effect.gen(function* () {
106323
106941
  return {
106324
106942
  type: "api",
@@ -106566,7 +107184,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
106566
107184
  sshUrl: `git@${fallbackHost}:${repository}.git`
106567
107185
  };
106568
107186
  }
106569
- const make$48 = Effect.gen(function* () {
107187
+ const make$46 = Effect.gen(function* () {
106570
107188
  const process = yield* VcsProcess;
106571
107189
  const execute = (input) => process.run({
106572
107190
  operation: "GitHubCli.execute",
@@ -106684,7 +107302,7 @@ const make$48 = Effect.gen(function* () {
106684
107302
  }).pipe(Effect.asVoid)
106685
107303
  });
106686
107304
  });
106687
- const layer$39 = Layer.effect(GitHubCli, make$48);
107305
+ const layer$37 = Layer.effect(GitHubCli, make$46);
106688
107306
  //#endregion
106689
107307
  //#region src/sourceControl/gitHubAuthStatus.ts
106690
107308
  const GitHubAuthStatusAccountSchema = Schema$1.Struct({
@@ -106786,7 +107404,7 @@ const discovery$1 = {
106786
107404
  parseAuth: parseGitHubAuth,
106787
107405
  installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
106788
107406
  };
106789
- const make$47 = Effect.gen(function* () {
107407
+ const make$45 = Effect.gen(function* () {
106790
107408
  const github = yield* GitHubCli;
106791
107409
  const listChangeRequests = (input) => {
106792
107410
  if (input.state === "open") return github.listOpenPullRequests({
@@ -106902,7 +107520,7 @@ const make$47 = Effect.gen(function* () {
106902
107520
  })))
106903
107521
  });
106904
107522
  });
106905
- Layer.effect(SourceControlProvider, make$47);
107523
+ Layer.effect(SourceControlProvider, make$45);
106906
107524
  //#endregion
106907
107525
  //#region src/sourceControl/gitLabMergeRequests.ts
106908
107526
  const GitLabProjectReferenceSchema = Schema$1.Struct({
@@ -107221,7 +107839,7 @@ function parseRepositoryPath(repository) {
107221
107839
  projectPath
107222
107840
  };
107223
107841
  }
107224
- const make$46 = Effect.gen(function* () {
107842
+ const make$44 = Effect.gen(function* () {
107225
107843
  const process = yield* VcsProcess;
107226
107844
  const run = (input, mapError) => process.run({
107227
107845
  operation: "GitLabCli.execute",
@@ -107372,7 +107990,7 @@ const make$46 = Effect.gen(function* () {
107372
107990
  }).pipe(Effect.asVoid)
107373
107991
  });
107374
107992
  });
107375
- const layer$37 = Layer.effect(GitLabCli, make$46);
107993
+ const layer$35 = Layer.effect(GitLabCli, make$44);
107376
107994
  //#endregion
107377
107995
  //#region src/sourceControl/gitLabAuthStatus.ts
107378
107996
  const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
@@ -107470,7 +108088,7 @@ const discovery = {
107470
108088
  refineUnknownRemote: refineUnknownGitLabRemote,
107471
108089
  installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
107472
108090
  };
107473
- const make$45 = Effect.gen(function* () {
108091
+ const make$43 = Effect.gen(function* () {
107474
108092
  const gitlab = yield* GitLabCli;
107475
108093
  return SourceControlProvider.of({
107476
108094
  kind: "gitlab",
@@ -107559,7 +108177,7 @@ const make$45 = Effect.gen(function* () {
107559
108177
  })))
107560
108178
  });
107561
108179
  });
107562
- Layer.effect(SourceControlProvider, make$45);
108180
+ Layer.effect(SourceControlProvider, make$43);
107563
108181
  //#endregion
107564
108182
  //#region src/sourceControl/SourceControlProviderRegistry.ts
107565
108183
  const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
@@ -107715,12 +108333,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
107715
108333
  })), { concurrency: "unbounded" })
107716
108334
  });
107717
108335
  });
107718
- const make$44 = Effect.gen(function* () {
107719
- const github = yield* make$47;
107720
- const gitlab = yield* make$45;
107721
- const bitbucket = yield* make$49;
108336
+ const make$42 = Effect.gen(function* () {
108337
+ const github = yield* make$45;
108338
+ const gitlab = yield* make$43;
108339
+ const bitbucket = yield* make$47;
107722
108340
  const bitbucketDiscovery = yield* makeDiscovery;
107723
- const azureDevOps = yield* make$51;
108341
+ const azureDevOps = yield* make$49;
107724
108342
  return yield* makeWithProviders([
107725
108343
  {
107726
108344
  kind: "github",
@@ -107744,7 +108362,7 @@ const make$44 = Effect.gen(function* () {
107744
108362
  }
107745
108363
  ]);
107746
108364
  });
107747
- const layer$35 = Layer.effect(SourceControlProviderRegistry, make$44);
108365
+ const layer$33 = Layer.effect(SourceControlProviderRegistry, make$42);
107748
108366
  //#endregion
107749
108367
  //#region src/sourceControl/PrTemplateDetection.ts
107750
108368
  const TEMPLATE_MAX_BYTES = 8e3;
@@ -108115,7 +108733,7 @@ function toPullRequestHeadRemoteInfo(pr) {
108115
108733
  ...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
108116
108734
  };
108117
108735
  }
108118
- const make$43 = Effect.gen(function* () {
108736
+ const make$41 = Effect.gen(function* () {
108119
108737
  const gitCore = yield* GitVcsDriver;
108120
108738
  const sourceControlProviders = yield* SourceControlProviderRegistry;
108121
108739
  const textGeneration = yield* TextGeneration;
@@ -109089,7 +109707,7 @@ const make$43 = Effect.gen(function* () {
109089
109707
  runStackedAction
109090
109708
  });
109091
109709
  });
109092
- const layer$34 = Layer.effect(GitManager, make$43);
109710
+ const layer$32 = Layer.effect(GitManager, make$41);
109093
109711
  //#endregion
109094
109712
  //#region src/git/GitWorkflowService.ts
109095
109713
  var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
@@ -109126,7 +109744,7 @@ function nonRepositoryListRefs() {
109126
109744
  totalCount: 0
109127
109745
  };
109128
109746
  }
109129
- const make$42 = Effect.gen(function* () {
109747
+ const make$40 = Effect.gen(function* () {
109130
109748
  const registry = yield* VcsDriverRegistry;
109131
109749
  const git = yield* GitVcsDriver;
109132
109750
  const gitManager = yield* GitManager;
@@ -109212,7 +109830,7 @@ const make$42 = Effect.gen(function* () {
109212
109830
  renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
109213
109831
  });
109214
109832
  });
109215
- const layer$33 = Layer.effect(GitWorkflowService, make$42);
109833
+ const layer$31 = Layer.effect(GitWorkflowService, make$40);
109216
109834
  //#endregion
109217
109835
  //#region src/pullRequest/PullRequestProvider.ts
109218
109836
  /**
@@ -109573,7 +110191,7 @@ function isReviewerName(value) {
109573
110191
  const name = value.trim();
109574
110192
  return name.length > 0 && !name.startsWith("-");
109575
110193
  }
109576
- const make$41 = Effect.gen(function* () {
110194
+ const make$39 = Effect.gen(function* () {
109577
110195
  const azure = yield* AzureDevOpsCli;
109578
110196
  const detectArgs = ["--detect", "true"];
109579
110197
  const executeJson = (input) => azure.execute({
@@ -109773,7 +110391,7 @@ const make$41 = Effect.gen(function* () {
109773
110391
  }).pipe(Effect.asVoid)
109774
110392
  });
109775
110393
  });
109776
- const layer$32 = Layer.effect(AzureDevOpsPullRequestCli, make$41);
110394
+ const layer$30 = Layer.effect(AzureDevOpsPullRequestCli, make$39);
109777
110395
  //#endregion
109778
110396
  //#region src/pullRequest/AzureDevOpsPullRequestProvider.ts
109779
110397
  const CAPABILITIES$3 = {
@@ -109848,7 +110466,7 @@ function toChangeRequest$1(pullRequest) {
109848
110466
  labels: []
109849
110467
  };
109850
110468
  }
109851
- const make$40 = Effect.gen(function* () {
110469
+ const make$38 = Effect.gen(function* () {
109852
110470
  const cli = yield* AzureDevOpsPullRequestCli;
109853
110471
  const fail = (operation) => (error) => new PullRequestProviderError({
109854
110472
  provider: "azure-devops",
@@ -110588,7 +111206,7 @@ function mergeStrategy(method) {
110588
111206
  default: return "merge_commit";
110589
111207
  }
110590
111208
  }
110591
- const make$39 = Effect.gen(function* () {
111209
+ const make$37 = Effect.gen(function* () {
110592
111210
  const bitbucket = yield* BitbucketApi;
110593
111211
  /**
110594
111212
  * The repository's own path, and the workspace above it — which the people who may review are
@@ -110868,7 +111486,7 @@ const make$39 = Effect.gen(function* () {
110868
111486
  }).pipe(Effect.asVoid))
110869
111487
  });
110870
111488
  });
110871
- const layer$31 = Layer.effect(BitbucketPullRequestApi, make$39);
111489
+ const layer$29 = Layer.effect(BitbucketPullRequestApi, make$37);
110872
111490
  //#endregion
110873
111491
  //#region src/pullRequest/BitbucketPullRequestProvider.ts
110874
111492
  const CAPABILITIES$2 = {
@@ -110948,7 +111566,7 @@ function toChangeRequest(pullRequest) {
110948
111566
  labels: []
110949
111567
  };
110950
111568
  }
110951
- const make$38 = Effect.gen(function* () {
111569
+ const make$36 = Effect.gen(function* () {
110952
111570
  const api = yield* BitbucketPullRequestApi;
110953
111571
  const fail = (operation) => (error) => new PullRequestProviderError({
110954
111572
  provider: "bitbucket",
@@ -113177,7 +113795,7 @@ function actionArgs$1(action, mergeMethod, updateMethod) {
113177
113795
  case "reopen": return ["reopen"];
113178
113796
  }
113179
113797
  }
113180
- const make$37 = Effect.gen(function* () {
113798
+ const make$35 = Effect.gen(function* () {
113181
113799
  const github = yield* GitHubCli;
113182
113800
  /**
113183
113801
  * The pull request's own node id, which is what a mutation against the pull request itself is
@@ -113940,7 +114558,7 @@ const make$37 = Effect.gen(function* () {
113940
114558
  })))
113941
114559
  });
113942
114560
  });
113943
- const layer$30 = Layer.effect(GitHubPullRequestCli, make$37);
114561
+ const layer$28 = Layer.effect(GitHubPullRequestCli, make$35);
113944
114562
  //#endregion
113945
114563
  //#region src/pullRequest/GitHubPullRequestProvider.ts
113946
114564
  const CAPABILITIES$1 = {
@@ -114057,7 +114675,7 @@ function loginAvatarUrl(login, host) {
114057
114675
  }
114058
114676
  /** True where markdown would render nothing: whitespace, or only HTML comments. */
114059
114677
  const rendersEmpty = (body) => body.replace(/<!--[\s\S]*?-->/g, "").trim().length === 0;
114060
- const make$36 = Effect.gen(function* () {
114678
+ const make$34 = Effect.gen(function* () {
114061
114679
  const cli = yield* GitHubPullRequestCli;
114062
114680
  const fail = (operation) => (error) => new PullRequestProviderError({
114063
114681
  provider: "github",
@@ -115079,7 +115697,7 @@ function actionArgs(action, mergeMethod) {
115079
115697
  case "reopen": return ["reopen"];
115080
115698
  }
115081
115699
  }
115082
- const make$35 = Effect.gen(function* () {
115700
+ const make$33 = Effect.gen(function* () {
115083
115701
  const gitlab = yield* GitLabCli;
115084
115702
  const api = (input) => gitlab.execute({
115085
115703
  cwd: input.cwd,
@@ -115650,7 +116268,7 @@ const make$35 = Effect.gen(function* () {
115650
116268
  }).pipe(Effect.asVoid)
115651
116269
  });
115652
116270
  });
115653
- const layer$29 = Layer.effect(GitLabPullRequestCli, make$35);
116271
+ const layer$27 = Layer.effect(GitLabPullRequestCli, make$33);
115654
116272
  //#endregion
115655
116273
  //#region src/pullRequest/GitLabPullRequestProvider.ts
115656
116274
  const CAPABILITIES = {
@@ -115730,7 +116348,7 @@ function reasonFor(error) {
115730
116348
  if (error._tag === "GitLabCliAuthenticationError") return "unauthenticated";
115731
116349
  return "failed";
115732
116350
  }
115733
- const make$34 = Effect.gen(function* () {
116351
+ const make$32 = Effect.gen(function* () {
115734
116352
  const cli = yield* GitLabPullRequestCli;
115735
116353
  const fail = (operation) => (error) => new PullRequestProviderError({
115736
116354
  provider: "gitlab",
@@ -115873,13 +116491,13 @@ function fromProviders(providers) {
115873
116491
  * The hosts this build can read change requests from. A host with no entry here still shows up
115874
116492
  * in the provider list as unimplemented, so its projects are explained rather than missing.
115875
116493
  */
115876
- const make$33 = Effect.map(Effect.all([
115877
- make$36,
116494
+ const make$31 = Effect.map(Effect.all([
115878
116495
  make$34,
115879
- make$38,
115880
- make$40
116496
+ make$32,
116497
+ make$36,
116498
+ make$38
115881
116499
  ]), fromProviders);
115882
- const layer$28 = Layer.effect(PullRequestProviderRegistry, make$33).pipe(Layer.provide(layer$30.pipe(Layer.provide(layer$39))), Layer.provide(layer$29.pipe(Layer.provide(layer$37))), Layer.provide(layer$31.pipe(Layer.provide(layer$41))), Layer.provide(layer$32.pipe(Layer.provide(layer$43))));
116500
+ const layer$26 = Layer.effect(PullRequestProviderRegistry, make$31).pipe(Layer.provide(layer$28.pipe(Layer.provide(layer$37))), Layer.provide(layer$27.pipe(Layer.provide(layer$35))), Layer.provide(layer$29.pipe(Layer.provide(layer$39))), Layer.provide(layer$30.pipe(Layer.provide(layer$41))));
115883
116501
  //#endregion
115884
116502
  //#region src/pullRequest/PullRequestService.ts
115885
116503
  /**
@@ -116067,7 +116685,7 @@ function repositoryIdentityOf(project) {
116067
116685
  if (identity.displayName) return identity.displayName;
116068
116686
  return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null;
116069
116687
  }
116070
- const make$32 = Effect.gen(function* () {
116688
+ const make$30 = Effect.gen(function* () {
116071
116689
  const registry = yield* PullRequestProviderRegistry;
116072
116690
  const projections = yield* ProjectionSnapshotQuery;
116073
116691
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -117065,7 +117683,7 @@ const make$32 = Effect.gen(function* () {
117065
117683
  invalidate
117066
117684
  });
117067
117685
  });
117068
- const layer$27 = Layer.effect(PullRequestService, make$32);
117686
+ const layer$25 = Layer.effect(PullRequestService, make$30);
117069
117687
  //#endregion
117070
117688
  //#region src/orchestration/ThreadWorkspaceLifecycle.ts
117071
117689
  var ThreadWorkspaceLifecycleError = class extends Data.TaggedError("ThreadWorkspaceLifecycleError") {};
@@ -117109,7 +117727,7 @@ const mapLifecycleError = Effect.mapError((cause) => cause instanceof ThreadWork
117109
117727
  detail: "Thread workspace lifecycle operation failed.",
117110
117728
  cause
117111
117729
  }));
117112
- const make$31 = Effect.gen(function* () {
117730
+ const make$29 = Effect.gen(function* () {
117113
117731
  const snapshots = yield* ProjectionSnapshotQuery;
117114
117732
  const engine = yield* OrchestrationEngineService;
117115
117733
  const gitWorkflow = yield* GitWorkflowService;
@@ -117363,7 +117981,7 @@ const make$31 = Effect.gen(function* () {
117363
117981
  record
117364
117982
  };
117365
117983
  });
117366
- const layer$26 = Layer.effect(ThreadWorkspaceLifecycleService, make$31);
117984
+ const layer$24 = Layer.effect(ThreadWorkspaceLifecycleService, make$29);
117367
117985
  //#endregion
117368
117986
  //#region src/textGeneration/BtwRequestCoordinator.ts
117369
117987
  const MAX_PENDING_BTW_CANCELLATIONS = 256;
@@ -119636,7 +120254,7 @@ function makeUpdateState(input) {
119636
120254
  output: input.output ?? null
119637
120255
  };
119638
120256
  }
119639
- const make$30 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
120257
+ const make$28 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
119640
120258
  const providerRegistry = yield* ProviderRegistry;
119641
120259
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
119642
120260
  const httpClient = yield* HttpClient.HttpClient;
@@ -119722,7 +120340,7 @@ const make$30 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
119722
120340
  status: stillOutdated ? "unchanged" : "succeeded",
119723
120341
  startedAt,
119724
120342
  finishedAt,
119725
- message: couldNotVerify ? "Update command completed, but P4Code could not verify the provider version." : stillOutdated ? "Update command completed, but P4Code still detects an outdated provider version." : "Provider updated.",
120343
+ message: couldNotVerify ? "Update command completed, but P4 Code could not verify the provider version." : stillOutdated ? "Update command completed, but P4 Code still detects an outdated provider version." : "Provider updated.",
119726
120344
  output: commandOutput(result)
119727
120345
  }));
119728
120346
  });
@@ -119751,7 +120369,7 @@ const make$30 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
119751
120369
  });
119752
120370
  return ProviderMaintenanceRunner.of({ updateProvider });
119753
120371
  });
119754
- const layer$25 = Layer.effect(ProviderMaintenanceRunner, make$30());
120372
+ const layer$23 = Layer.effect(ProviderMaintenanceRunner, make$28());
119755
120373
  //#endregion
119756
120374
  //#region src/usage/usageTranscripts.ts
119757
120375
  const EMPTY_TOTALS = {
@@ -120574,7 +121192,7 @@ Layer.succeed(UsageService, UsageService.of({ readSummary: (input) => Effect.suc
120574
121192
  },
120575
121193
  scanDurationMs: 0
120576
121194
  }) }));
120577
- const make$29 = Effect.gen(function* () {
121195
+ const make$27 = Effect.gen(function* () {
120578
121196
  const fileSystem = yield* FileSystem.FileSystem;
120579
121197
  const path = yield* Path$1.Path;
120580
121198
  const config = yield* ServerConfig$1;
@@ -120816,7 +121434,7 @@ const make$29 = Effect.gen(function* () {
120816
121434
  };
120817
121435
  }) };
120818
121436
  });
120819
- const layer$24 = Layer.effect(UsageService, make$29);
121437
+ const layer$22 = Layer.effect(UsageService, make$27);
120820
121438
  //#endregion
120821
121439
  //#region src/feed/FeedStore.ts
120822
121440
  const storageFailure = (message) => new FeedError({
@@ -121180,7 +121798,7 @@ const jsonRequest = Effect.fn("FeedService.jsonRequest")(function* (url, token,
121180
121798
  catch: () => fail("hub_unavailable", "Hub returned invalid JSON.")
121181
121799
  });
121182
121800
  });
121183
- const make$28 = Effect.gen(function* () {
121801
+ const make$26 = Effect.gen(function* () {
121184
121802
  const hubLink = yield* HubLink;
121185
121803
  const providers = yield* ProviderInstanceRegistry;
121186
121804
  const config = yield* ServerConfig$1;
@@ -121418,7 +122036,7 @@ var FeedService = class extends Context.Reference("@p4code/cli/feed/FeedService"
121418
122036
  markRead: unavailable,
121419
122037
  cleanup: unavailable
121420
122038
  }) }) {};
121421
- const layer$23 = Layer.effect(FeedService, make$28);
122039
+ const layer$21 = Layer.effect(FeedService, make$26);
121422
122040
  const SKILL_MANIFEST_FILENAME = "SKILL.md";
121423
122041
  /**
121424
122042
  * Split a catalogue id (`owner/repo/skill-name`) into its parts.
@@ -121564,7 +122182,7 @@ const emptyFetch = (id, unavailable) => ({
121564
122182
  skipped: [],
121565
122183
  unavailable
121566
122184
  });
121567
- const make$27 = Effect.gen(function* () {
122185
+ const make$25 = Effect.gen(function* () {
121568
122186
  const http = yield* HttpClient.HttpClient;
121569
122187
  const request = Effect.fn("SkillRegistry.request")(function* (url) {
121570
122188
  return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS$1));
@@ -121635,117 +122253,7 @@ const make$27 = Effect.gen(function* () {
121635
122253
  fetch
121636
122254
  };
121637
122255
  });
121638
- const layer$22 = Layer.effect(SkillRegistry, make$27);
121639
- //#endregion
121640
- //#region src/mcp/McpInvocationContext.ts
121641
- var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
121642
- const requireMcpCapability = Effect.fn("mcp.requireCapability")(function* (capability) {
121643
- const invocation = yield* McpInvocationContext;
121644
- if (!invocation.capabilities.has(capability)) return yield* new PreviewAutomationUnavailableError({
121645
- capability,
121646
- environmentId: invocation.environmentId,
121647
- threadId: invocation.threadId,
121648
- providerSessionId: invocation.providerSessionId,
121649
- providerInstanceId: invocation.providerInstanceId
121650
- });
121651
- return invocation;
121652
- });
121653
- /**
121654
- * The task-board counterpart of {@link requireMcpCapability}. The two are
121655
- * separate because each capability reports its own absence with the error type
121656
- * its toolkit declares as a failure, and those unions do not overlap.
121657
- */
121658
- const requireTaskCapability = Effect.fn("mcp.requireTaskCapability")(function* () {
121659
- const invocation = yield* McpInvocationContext;
121660
- if (!invocation.capabilities.has("tasks")) return yield* new TaskToolUnavailableError({
121661
- capability: "tasks",
121662
- environmentId: invocation.environmentId,
121663
- threadId: invocation.threadId,
121664
- providerSessionId: invocation.providerSessionId,
121665
- providerInstanceId: invocation.providerInstanceId
121666
- });
121667
- return invocation;
121668
- });
121669
- /**
121670
- * The watch capability's guard is two checks, not one: the capability must be
121671
- * present AND the requested thread must be in the explicit grant set. The two
121672
- * failures are distinct errors so a watcher can tell "this session cannot
121673
- * watch at all" apart from "not this thread".
121674
- */
121675
- const requireWatchCapability = Effect.fn("mcp.requireWatchCapability")(function* (watchedThreadId) {
121676
- const invocation = yield* McpInvocationContext;
121677
- if (!invocation.capabilities.has("watch")) return yield* new WatchToolUnavailableError({
121678
- capability: "watch",
121679
- environmentId: invocation.environmentId,
121680
- threadId: invocation.threadId,
121681
- providerSessionId: invocation.providerSessionId,
121682
- providerInstanceId: invocation.providerInstanceId
121683
- });
121684
- if (!invocation.watchThreadIds?.has(watchedThreadId)) return yield* new ThreadWatchNotPermittedError({ threadId: watchedThreadId });
121685
- return invocation;
121686
- });
121687
- /**
121688
- * The advise guard mirrors the watch guard's two checks - capability present
121689
- * AND thread in the explicit grant - because advising carries strictly more
121690
- * power than watching. A watch-only credential fails the first check here no
121691
- * matter what threads it can read.
121692
- */
121693
- const requireAdviseCapability = Effect.fn("mcp.requireAdviseCapability")(function* (advisedThreadId) {
121694
- const invocation = yield* McpInvocationContext;
121695
- if (!invocation.capabilities.has("advise")) return yield* new AdviseToolUnavailableError({
121696
- capability: "advise",
121697
- environmentId: invocation.environmentId,
121698
- threadId: invocation.threadId,
121699
- providerSessionId: invocation.providerSessionId,
121700
- providerInstanceId: invocation.providerInstanceId
121701
- });
121702
- if (!invocation.adviseThreadIds?.has(advisedThreadId)) return yield* new ThreadAdviseNotPermittedError({ threadId: advisedThreadId });
121703
- return invocation;
121704
- });
121705
- /** Third of the trio, for the same reason the second exists. */
121706
- const requireThreadCapability = Effect.fn("mcp.requireThreadCapability")(function* () {
121707
- const invocation = yield* McpInvocationContext;
121708
- if (!invocation.capabilities.has("threads")) return yield* new ThreadToolUnavailableError({
121709
- capability: "threads",
121710
- environmentId: invocation.environmentId,
121711
- threadId: invocation.threadId,
121712
- providerSessionId: invocation.providerSessionId,
121713
- providerInstanceId: invocation.providerInstanceId
121714
- });
121715
- return invocation;
121716
- });
121717
- /**
121718
- * The thread a control tool may act on, given what it was asked to act on.
121719
- *
121720
- * Two checks like `requireWatchCapability`, and for the same reason: the
121721
- * capability says this session controls threads at all, the grant says which.
121722
- * An omitted id resolves to the session's own thread, which is always in the
121723
- * grant and is why the common call needs no id and so cannot name a wrong one.
121724
- */
121725
- const requireThreadControlTarget = Effect.fn("mcp.requireThreadControlTarget")(function* (requested) {
121726
- const invocation = yield* requireThreadCapability();
121727
- if (requested === void 0 || requested === invocation.threadId) return {
121728
- invocation,
121729
- threadId: invocation.threadId
121730
- };
121731
- if (!invocation.controlThreadIds?.has(requested)) return yield* new ThreadControlNotPermittedError({ threadId: requested });
121732
- return {
121733
- invocation,
121734
- threadId: requested
121735
- };
121736
- });
121737
- /**
121738
- * The guard on starting a thread, which is a different question from acting on
121739
- * one: it is not "which thread" but "may this session make more of them".
121740
- */
121741
- const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* (fusion = false) {
121742
- const invocation = yield* requireThreadCapability();
121743
- if (invocation.mayCreateThreads !== true && !(fusion && invocation.mayCreateFusionPairs === true)) return yield* new ThreadSpawnNotPermittedError({
121744
- threadId: invocation.threadId,
121745
- detail: "this thread was itself started by an agent, and spawning goes one level deep so a runaway loop has a bound"
121746
- });
121747
- return invocation;
121748
- });
122256
+ const layer$20 = Layer.effect(SkillRegistry, make$25);
121749
122257
  //#endregion
121750
122258
  //#region src/mcp/PreviewAutomationBroker.ts
121751
122259
  var PreviewAutomationBroker = class extends Context.Service()("@p4code/cli/mcp/PreviewAutomationBroker") {};
@@ -121863,7 +122371,7 @@ const classifyResponseError = (context, error) => {
121863
122371
  });
121864
122372
  }
121865
122373
  };
121866
- const make$26 = Effect.gen(function* PreviewAutomationBrokerMake() {
122374
+ const make$24 = Effect.gen(function* PreviewAutomationBrokerMake() {
121867
122375
  const crypto = yield* Crypto.Crypto;
121868
122376
  const state = yield* SynchronizedRef.make({
121869
122377
  clients: /* @__PURE__ */ new Map(),
@@ -122097,7 +122605,7 @@ const make$26 = Effect.gen(function* PreviewAutomationBrokerMake() {
122097
122605
  invoke
122098
122606
  });
122099
122607
  }).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
122100
- const layer$21 = Layer.effect(PreviewAutomationBroker, make$26);
122608
+ const layer$19 = Layer.effect(PreviewAutomationBroker, make$24);
122101
122609
  //#endregion
122102
122610
  //#region src/preview/Manager.ts
122103
122611
  /**
@@ -122161,7 +122669,7 @@ const buildIdleSnapshot = (input) => ({
122161
122669
  viewport: FILL_PREVIEW_VIEWPORT,
122162
122670
  updatedAt: input.updatedAt
122163
122671
  });
122164
- const make$25 = Effect.gen(function* PreviewManagerMake() {
122672
+ const make$23 = Effect.gen(function* PreviewManagerMake() {
122165
122673
  const serverEpoch = NodeCrypto.randomUUID();
122166
122674
  const stateRef = yield* SynchronizedRef.make(initialState);
122167
122675
  const eventsPubSub = yield* PubSub.unbounded();
@@ -122392,7 +122900,7 @@ const make$25 = Effect.gen(function* PreviewManagerMake() {
122392
122900
  subscribeEvents: PubSub.subscribe(eventsPubSub)
122393
122901
  });
122394
122902
  }).pipe(Effect.withSpan("PreviewManager.make"));
122395
- const layer$20 = Layer.effect(PreviewManager, make$25);
122903
+ const layer$18 = Layer.effect(PreviewManager, make$23);
122396
122904
  //#endregion
122397
122905
  //#region src/workspace/WorkspaceSearchIndex.ts
122398
122906
  const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
@@ -122529,7 +123037,7 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
122529
123037
  timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
122530
123038
  })
122531
123039
  }), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
122532
- const make$24 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
123040
+ const make$22 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
122533
123041
  const finder = yield* Effect.acquireRelease(createFinder(cwd, contentSearch), (finder) => Effect.try({
122534
123042
  try: () => finder.destroy(),
122535
123043
  catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
@@ -122669,14 +123177,14 @@ const make$24 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSe
122669
123177
  * workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
122670
123178
  * using a default cwd here would mix resources from different workspaces.
122671
123179
  */
122672
- const layer$19 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$24(cwd));
123180
+ const layer$17 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$22(cwd));
122673
123181
  var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
122674
- lookup: layer$19,
123182
+ lookup: layer$17,
122675
123183
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
122676
123184
  }) {};
122677
123185
  /** Content indexing is allocated only when workspace content search is used. */
122678
123186
  var WorkspaceContentSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceContentSearchIndexMap", {
122679
- lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$24(cwd, true)),
123187
+ lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$22(cwd, true)),
122680
123188
  idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
122681
123189
  }) {};
122682
123190
  //#endregion
@@ -122738,7 +123246,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
122738
123246
  if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
122739
123247
  return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
122740
123248
  });
122741
- const make$23 = Effect.gen(function* () {
123249
+ const make$21 = Effect.gen(function* () {
122742
123250
  const path = yield* Path$1.Path;
122743
123251
  const workspacePaths = yield* WorkspacePaths;
122744
123252
  const contentSearchIndexes = yield* WorkspaceContentSearchIndexMap;
@@ -122820,7 +123328,7 @@ const make$23 = Effect.gen(function* () {
122820
123328
  searchContents
122821
123329
  });
122822
123330
  });
122823
- const layer$18 = Layer.effect(WorkspaceEntries, make$23).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
123331
+ const layer$16 = Layer.effect(WorkspaceEntries, make$21).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
122824
123332
  //#endregion
122825
123333
  //#region src/workspace/WorkspaceFileSystem.ts
122826
123334
  /**
@@ -122879,7 +123387,7 @@ Schema$1.Union([
122879
123387
  ]);
122880
123388
  /** Service tag for workspace file operations. */
122881
123389
  var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
122882
- const make$22 = Effect.gen(function* () {
123390
+ const make$20 = Effect.gen(function* () {
122883
123391
  const fileSystem = yield* FileSystem.FileSystem;
122884
123392
  const path = yield* Path$1.Path;
122885
123393
  const workspacePaths = yield* WorkspacePaths;
@@ -123023,7 +123531,7 @@ const make$22 = Effect.gen(function* () {
123023
123531
  writeFile
123024
123532
  });
123025
123533
  });
123026
- const layer$17 = Layer.effect(WorkspaceFileSystem, make$22);
123534
+ const layer$15 = Layer.effect(WorkspaceFileSystem, make$20);
123027
123535
  //#endregion
123028
123536
  //#region src/vcs/VcsStatusBroadcaster.ts
123029
123537
  const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
@@ -123105,7 +123613,7 @@ const autoPullPolicyLayer = Layer.effect(VcsAutoPullPolicy, Effect.gen(function*
123105
123613
  return resolveProjectAutoPull(yield* settingsService.getSettings, project.value.id);
123106
123614
  }, Effect.orElseSucceed(() => false)) };
123107
123615
  }));
123108
- const make$21 = Effect.gen(function* () {
123616
+ const make$19 = Effect.gen(function* () {
123109
123617
  const autoPullPolicy = yield* VcsAutoPullPolicy;
123110
123618
  const workflow = yield* GitWorkflowService;
123111
123619
  const fs = yield* FileSystem.FileSystem;
@@ -123364,7 +123872,7 @@ const make$21 = Effect.gen(function* () {
123364
123872
  streamStatus
123365
123873
  });
123366
123874
  });
123367
- const layer$16 = Layer.effect(VcsStatusBroadcaster, make$21);
123875
+ const layer$14 = Layer.effect(VcsStatusBroadcaster, make$19);
123368
123876
  //#endregion
123369
123877
  //#region src/vcs/VcsProvisioningService.ts
123370
123878
  var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
@@ -123377,7 +123885,7 @@ function resolveRequestedKind(kind) {
123377
123885
  }));
123378
123886
  return Effect.succeed(kind);
123379
123887
  }
123380
- const make$20 = Effect.gen(function* () {
123888
+ const make$18 = Effect.gen(function* () {
123381
123889
  const registry = yield* VcsDriverRegistry;
123382
123890
  const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
123383
123891
  const kind = yield* resolveRequestedKind(input.kind);
@@ -123385,11 +123893,11 @@ const make$20 = Effect.gen(function* () {
123385
123893
  });
123386
123894
  return VcsProvisioningService.of({ initRepository });
123387
123895
  });
123388
- const layer$15 = Layer.effect(VcsProvisioningService, make$20);
123896
+ const layer$13 = Layer.effect(VcsProvisioningService, make$18);
123389
123897
  //#endregion
123390
123898
  //#region src/review/ReviewService.ts
123391
123899
  var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
123392
- const make$19 = Effect.gen(function* () {
123900
+ const make$17 = Effect.gen(function* () {
123393
123901
  const config = yield* ServerConfig$1;
123394
123902
  const fileSystem = yield* FileSystem.FileSystem;
123395
123903
  const path = yield* Path$1.Path;
@@ -123445,7 +123953,7 @@ const make$19 = Effect.gen(function* () {
123445
123953
  });
123446
123954
  return ReviewService.of({ getDiffPreview });
123447
123955
  });
123448
- const layer$14 = Layer.effect(ReviewService, make$19);
123956
+ const layer$12 = Layer.effect(ReviewService, make$17);
123449
123957
  //#endregion
123450
123958
  //#region src/diagnostics/ProcessDiagnostics.ts
123451
123959
  const PROCESS_QUERY_TIMEOUT_MS = 1e3;
@@ -123740,7 +124248,7 @@ function assertDescendantPid(pid) {
123740
124248
  }));
123741
124249
  }));
123742
124250
  }
123743
- const make$18 = Effect.gen(function* () {
124251
+ const make$16 = Effect.gen(function* () {
123744
124252
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
123745
124253
  const read = Effect.gen(function* () {
123746
124254
  const readAt = yield* DateTime.now;
@@ -123784,7 +124292,7 @@ const make$18 = Effect.gen(function* () {
123784
124292
  signal
123785
124293
  });
123786
124294
  });
123787
- const layer$13 = Layer.effect(ProcessDiagnostics, make$18);
124295
+ const layer$11 = Layer.effect(ProcessDiagnostics, make$16);
123788
124296
  //#endregion
123789
124297
  //#region src/diagnostics/ProcessResourceMonitor.ts
123790
124298
  const SAMPLE_INTERVAL_MS = 5e3;
@@ -123935,7 +124443,7 @@ function aggregateProcessResourceHistory(input) {
123935
124443
  }) : Option.none()
123936
124444
  };
123937
124445
  }
123938
- const make$17 = Effect.gen(function* () {
124446
+ const make$15 = Effect.gen(function* () {
123939
124447
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
123940
124448
  const state = yield* Ref.make({
123941
124449
  samples: [],
@@ -123984,7 +124492,7 @@ const make$17 = Effect.gen(function* () {
123984
124492
  });
123985
124493
  return ProcessResourceMonitor.of({ readHistory });
123986
124494
  });
123987
- const layer$12 = Layer.effect(ProcessResourceMonitor, make$17);
124495
+ const layer$10 = Layer.effect(ProcessResourceMonitor, make$15);
123988
124496
  //#endregion
123989
124497
  //#region src/diagnostics/TraceDiagnostics.ts
123990
124498
  var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
@@ -124232,7 +124740,7 @@ function readTraceFile(fileSystem, path) {
124232
124740
  cause
124233
124741
  })) }));
124234
124742
  }
124235
- const make$16 = Effect.gen(function* () {
124743
+ const make$14 = Effect.gen(function* () {
124236
124744
  const fileSystem = yield* FileSystem.FileSystem;
124237
124745
  const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
124238
124746
  const readAt = options.readAt ?? (yield* DateTime.now);
@@ -124276,7 +124784,7 @@ const make$16 = Effect.gen(function* () {
124276
124784
  });
124277
124785
  return TraceDiagnostics.of({ read });
124278
124786
  });
124279
- const layer$11 = Layer.effect(TraceDiagnostics, make$16);
124787
+ const layer$9 = Layer.effect(TraceDiagnostics, make$14);
124280
124788
  function readTraceDiagnostics(options) {
124281
124789
  return Effect.gen(function* () {
124282
124790
  return yield* (yield* TraceDiagnostics).read(options);
@@ -124311,7 +124819,7 @@ function snapshotFromDetail(link, detail, syncedAt) {
124311
124819
  mergeability: detail.mergeability
124312
124820
  };
124313
124821
  }
124314
- const make$15 = Effect.gen(function* () {
124822
+ const make$13 = Effect.gen(function* () {
124315
124823
  const engine = yield* OrchestrationEngineService;
124316
124824
  const projections = yield* ProjectionSnapshotQuery;
124317
124825
  const pullRequests = yield* PullRequestService;
@@ -124405,7 +124913,7 @@ const make$15 = Effect.gen(function* () {
124405
124913
  };
124406
124914
  });
124407
124915
  var PullRequestSyncReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/PullRequestSyncReactor") {};
124408
- const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$15);
124916
+ const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$13);
124409
124917
  //#endregion
124410
124918
  //#region src/sourceControl/SourceControlDiscovery.ts
124411
124919
  const VCS_PROBES = [{
@@ -124424,7 +124932,7 @@ const VCS_PROBES = [{
124424
124932
  installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
124425
124933
  }];
124426
124934
  var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
124427
- const make$14 = Effect.gen(function* () {
124935
+ const make$12 = Effect.gen(function* () {
124428
124936
  const config = yield* ServerConfig$1;
124429
124937
  const process = yield* VcsProcess;
124430
124938
  const sourceControlProviders = yield* SourceControlProviderRegistry;
@@ -124473,7 +124981,7 @@ const make$14 = Effect.gen(function* () {
124473
124981
  sourceControlProviders: sourceControlProviders.discover
124474
124982
  }) });
124475
124983
  });
124476
- const layer$10 = Layer.effect(SourceControlDiscovery, make$14);
124984
+ const layer$8 = Layer.effect(SourceControlDiscovery, make$12);
124477
124985
  //#endregion
124478
124986
  //#region src/sourceControl/SourceControlRepositoryService.ts
124479
124987
  const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
@@ -124506,7 +125014,7 @@ function expandHomePath(input, path) {
124506
125014
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
124507
125015
  return input;
124508
125016
  }
124509
- const make$13 = Effect.gen(function* () {
125017
+ const make$11 = Effect.gen(function* () {
124510
125018
  const config = yield* ServerConfig$1;
124511
125019
  const fileSystem = yield* FileSystem.FileSystem;
124512
125020
  const git = yield* GitVcsDriver;
@@ -124645,7 +125153,7 @@ const make$13 = Effect.gen(function* () {
124645
125153
  publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
124646
125154
  });
124647
125155
  });
124648
- const layer$9 = Layer.effect(SourceControlRepositoryService, make$13);
125156
+ const layer$7 = Layer.effect(SourceControlRepositoryService, make$11);
124649
125157
  //#endregion
124650
125158
  //#region src/ws.ts
124651
125159
  /** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
@@ -124899,6 +125407,7 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
124899
125407
  [WS_METHODS.computerUseConnect, AuthOrchestrationOperateScope],
124900
125408
  [WS_METHODS.computerUseList, AuthOrchestrationReadScope],
124901
125409
  [WS_METHODS.computerUseControls, AuthOrchestrationReadScope],
125410
+ [WS_METHODS.computerUsePreview, AuthOrchestrationReadScope],
124902
125411
  [WS_METHODS.computerUseControl, AuthOrchestrationOperateScope],
124903
125412
  [WS_METHODS.computerUseRespond, AuthOrchestrationOperateScope],
124904
125413
  [WS_METHODS.previewAutomationConnect, AuthOrchestrationOperateScope],
@@ -125989,6 +126498,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
125989
126498
  [WS_METHODS.previewReportStatus]: (input) => observeRpcEffect$1(WS_METHODS.previewReportStatus, previewManager.reportStatus(input), { "rpc.aggregate": "preview" }),
125990
126499
  [WS_METHODS.computerUseList]: () => computerUseBroker.list,
125991
126500
  [WS_METHODS.computerUseControls]: () => computerUseBroker.controls,
126501
+ [WS_METHODS.computerUsePreview]: (input) => computerUseBroker.preview(input),
125992
126502
  [WS_METHODS.computerUseControl]: (input) => computerUseBroker.control(input),
125993
126503
  [WS_METHODS.computerUseConnect]: () => Effect.fail(new ComputerUseError({
125994
126504
  reason: "denied",
@@ -126083,7 +126593,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
126083
126593
  const serverAuth = yield* EnvironmentAuth;
126084
126594
  const sessions = yield* SessionStore;
126085
126595
  const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
126086
- const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker, computerUseBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$25), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(PullRequestService, pullRequests)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$10.pipe(Layer.provide(layer$35.pipe(Layer.provide(Layer.mergeAll(layer$43, layer$41, layer$39, layer$37)), Layer.provideMerge(layer$51), Layer.provide(layer$49.pipe(Layer.provide(layer$50))))), Layer.provide(layer$52))))));
126596
+ const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker, computerUseBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$23), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(PullRequestService, pullRequests)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$8.pipe(Layer.provide(layer$33.pipe(Layer.provide(Layer.mergeAll(layer$41, layer$39, layer$37, layer$35)), Layer.provideMerge(layer$49), Layer.provide(layer$47.pipe(Layer.provide(layer$48))))), Layer.provide(layer$50))))));
126087
126597
  return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
126088
126598
  }).pipe(Effect.catchTags({
126089
126599
  EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
@@ -126148,7 +126658,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
126148
126658
  cause
126149
126659
  });
126150
126660
  }
126151
- const make$12 = Effect.gen(function* () {
126661
+ const make$10 = Effect.gen(function* () {
126152
126662
  const sql = yield* SqlClient.SqlClient;
126153
126663
  const upsertRuntimeRow = SqlSchema.void({
126154
126664
  Request: ProviderSessionRuntimeDbRowSchema,
@@ -126251,7 +126761,7 @@ const make$12 = Effect.gen(function* () {
126251
126761
  deleteByThreadId
126252
126762
  };
126253
126763
  });
126254
- const layer$8 = Layer.effect(ProviderSessionRuntimeRepository, make$12);
126764
+ const layer$6 = Layer.effect(ProviderSessionRuntimeRepository, make$10);
126255
126765
  //#endregion
126256
126766
  //#region src/provider/Layers/ProviderSessionDirectory.ts
126257
126767
  const decodeProviderDriverKindValue = Schema$1.decodeUnknownEffect(ProviderDriverKind);
@@ -126704,7 +127214,7 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
126704
127214
  });
126705
127215
  });
126706
127216
  let activeMcpSessionRegistry;
126707
- const make$11 = Effect.acquireRelease(Effect.gen(function* () {
127217
+ const make$9 = Effect.acquireRelease(Effect.gen(function* () {
126708
127218
  const broker = yield* Effect.serviceOption(ComputerUseBroker);
126709
127219
  return yield* makeWithOptions(Option.isSome(broker) ? { onRevoke: broker.value.invalidate } : {});
126710
127220
  }).pipe(Effect.tap((registry) => Effect.sync(() => {
@@ -126712,7 +127222,7 @@ const make$11 = Effect.acquireRelease(Effect.gen(function* () {
126712
127222
  }))), (registry) => registry.revokeAll.pipe(Effect.andThen(Effect.sync(() => {
126713
127223
  if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
126714
127224
  }))));
126715
- const layer$7 = Layer.effect(McpSessionRegistry, make$11);
127225
+ const layer$5 = Layer.effect(McpSessionRegistry, make$9);
126716
127226
  const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
126717
127227
  /**
126718
127228
  * Refreshes the liveness of a thread's MCP credential. Called on every provider
@@ -127094,7 +127604,7 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
127094
127604
  threadId,
127095
127605
  provider: resolvedProvider
127096
127606
  };
127097
- if (!instanceInfo.enabled) return yield* toValidationError("ProviderService.startSession", `Provider instance '${resolvedInstanceId}' is disabled in P4Code settings.`);
127607
+ if (!instanceInfo.enabled) return yield* toValidationError("ProviderService.startSession", `Provider instance '${resolvedInstanceId}' is disabled in P4 Code settings.`);
127098
127608
  const persistedBinding = Option.getOrUndefined(yield* directory.getBinding(threadId));
127099
127609
  const effectiveResumeCursor = input.resumeCursor ?? (persistedBinding?.providerInstanceId === resolvedInstanceId ? persistedBinding.resumeCursor : void 0);
127100
127610
  const effectiveCwd = input.cwd ?? (persistedBinding?.providerInstanceId === resolvedInstanceId ? readPersistedCwd(persistedBinding.runtimePayload) : void 0);
@@ -127183,7 +127693,10 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
127183
127693
  status: "running",
127184
127694
  ...turn.resumeCursor !== void 0 ? { resumeCursor: turn.resumeCursor } : {},
127185
127695
  runtimePayload: {
127186
- ...input.modelSelection !== void 0 ? { modelSelection: input.modelSelection } : {},
127696
+ ...input.modelSelection !== void 0 ? {
127697
+ model: input.modelSelection.model,
127698
+ modelSelection: input.modelSelection
127699
+ } : {},
127187
127700
  activeTurnId: turn.turnId,
127188
127701
  lastRuntimeEvent: "provider.sendTurn",
127189
127702
  lastRuntimeEventAt: yield* nowIso
@@ -127657,7 +128170,7 @@ const mcpToolkit = (toolkit) => Layer.effectDiscard(Effect.gen(function* () {
127657
128170
  //#endregion
127658
128171
  //#region src/mcp/toolkits/computerUse/tools.ts
127659
128172
  const ComputerUseJsTool = Tool.make("js", {
127660
- description: "Run JavaScript in a persistent P4 Computer Use REPL. Start with await cua.getState(). Use cua.createBrowserTab('iab', url, {visible:true}) or cua.getTab(tabId) for P4 browser tabs. Tab methods: getState(), goto(url), click({locator}), type({text,locator?,clear?}), press({key,modifiers?}), scroll({deltaY,deltaX?}). Print results with nodeRepl.write(value); emit PNG/JPEG with nodeRepl.emitImage({mimeType,data}) using base64 data. Top-level await and persistent let bindings are supported. Await each operation. Reset after timeout or host disconnect. For available native apps, use cua.getApp(exactNameOrBundleId), then getState(), activate(), click({elementId}), or type({elementId,text}) to replace a field value. Element IDs come from the latest app snapshot. List windows with app.windows(); capture a listed ID with app.screenshot(windowId), then nodeRepl.emitImage(image). Native app availability and macOS permission states are reported by the host; never assume native apps are supported. The host may be a different machine from the provider server.",
128173
+ description: "Run JavaScript in a persistent P4 Computer Use REPL. Start with await cua.getState(). Use cua.createBrowserTab('iab', url, {visible:true}) or cua.getTab(tabId) for P4 browser tabs. Tab methods: getState(), goto(url), click({locator}), type({text,locator?,clear?}), press({key,modifiers?}), scroll({deltaY,deltaX?}). Print results with nodeRepl.write(value); emit PNG/JPEG with nodeRepl.emitImage({mimeType,data}) using base64 data. Top-level await and persistent let bindings are supported. Await each operation. Reset after timeout or host disconnect. For available native apps, use cua.getApp(exactNameOrBundleId), then getAXState(), click(elementIndex), or setValue(elementIndex,text) to replace a field value in the background. Selection and getAXState print numbered accessibility state; Several deterministic actions against distinct unchanged elements may share one snapshot. Each used handle expires; the host revalidates remaining native handles and rejects changed elements. Read fresh state after the action batch before deciding the next action. getScreenshot() emits the selected app window; getAXStateAndScreenshot() emits both. Legacy getState(), click({elementId}), type({elementId,text}), windows(), and screenshot(windowId) remain supported. Native control preserves foreground focus and the system pointer. Coordinate, key, drag, scroll, and activation input are unsupported; do not use global input or activate the app as a fallback. P4Code shows the controlled native window and a persistent independent white pointer with a blue glow in its embedded live view. Hide closes only the view; use Show live view in the Computer Use control to reopen it. Stop ends thread control; reset clears the view and handles. Google Chrome can be controlled as a native app using cua.getApp('Google Chrome'); Chrome extension/CDP tab APIs are not exposed by this host. Native app availability and macOS permission states are reported by the host; never assume native apps are supported. The host may be a different machine from the provider server. Device hub simulators are scoped to the provider environment: await cua.listDevices(), then await cua.getDevice({hostId,deviceId,platform}) using exact discovered IDs. The device handle supports getAXState() (raw iOS accessibility state), getScreenshot(), getAXStateAndScreenshot(), click([x,y]) in device coordinates from fresh AX state, typeText(text), and close(). No device key, scroll, or drag APIs are currently exposed. Device consent must already be enabled in P4 Settings. Use timeout_ms:60000 for initial device startup. Reset invalidates device handles; device viewer sessions remain under Devices until explicitly closed. Never substitute macOS Simulator.app AX for simulated-app state.",
127661
128174
  parameters: Schema$1.Struct({
127662
128175
  ...ComputerUseJsInput.fields,
127663
128176
  hostId: Schema$1.optional(TrimmedNonEmptyString).annotate({ description: "Select an available host when more than one is connected. Reset before changing hosts." })
@@ -127730,163 +128243,6 @@ const register = Effect.fn("computerUse.register")(function* () {
127730
128243
  /** Images use MCP image blocks instead of returning base64 in text output. */
127731
128244
  const ComputerUseToolkitRegistrationLive = Layer.effectDiscard(register()).pipe(Layer.provide(ComputerUseToolkitHandlersLive));
127732
128245
  //#endregion
127733
- //#region src/device/DeviceScreenshot.ts
127734
- const MAX_SCREENSHOT_BYTES = 8 * 1024 * 1024;
127735
- var DeviceScreenshotFailure = class extends Data.TaggedError("DeviceScreenshotFailure") {};
127736
- const MAX_DIMENSION = 16384;
127737
- const MAX_PIXELS = 64 * 1024 * 1024;
127738
- const SCREENSHOT_TIMEOUT_MS = 2e4;
127739
- const PNG_HEADER_BYTES = 33;
127740
- const PNG_CHUNK_OVERHEAD = 12;
127741
- const PNG_SIGNATURE = Buffer.from([
127742
- 137,
127743
- 80,
127744
- 78,
127745
- 71,
127746
- 13,
127747
- 10,
127748
- 26,
127749
- 10
127750
- ]);
127751
- function pngDimensions(png) {
127752
- const buffer = Buffer.from(png.buffer, png.byteOffset, png.byteLength);
127753
- if (buffer.length < PNG_HEADER_BYTES || buffer.length > 8388608 || !buffer.subarray(0, PNG_SIGNATURE.length).equals(PNG_SIGNATURE) || buffer.readUInt32BE(8) !== 13 || buffer.toString("ascii", 12, 16) !== "IHDR") throw new DeviceScreenshotFailure({ message: "Invalid PNG screenshot." });
127754
- const width = buffer.readUInt32BE(16);
127755
- const height = buffer.readUInt32BE(20);
127756
- if (!width || !height || width > MAX_DIMENSION || height > MAX_DIMENSION || width * height > MAX_PIXELS) throw new DeviceScreenshotFailure({ message: "Screenshot dimensions exceed limits." });
127757
- let offset = PNG_HEADER_BYTES;
127758
- let imageData = false;
127759
- let ended = false;
127760
- while (offset + PNG_CHUNK_OVERHEAD <= buffer.length) {
127761
- const length = buffer.readUInt32BE(offset);
127762
- const type = buffer.toString("ascii", offset + 4, offset + 8);
127763
- const next = offset + PNG_CHUNK_OVERHEAD + length;
127764
- if (next > buffer.length || type === "IHDR") throw new DeviceScreenshotFailure({ message: "Invalid PNG chunk." });
127765
- if (type === "IDAT") imageData = true;
127766
- if (type === "IEND") {
127767
- ended = length === 0 && next === buffer.length;
127768
- break;
127769
- }
127770
- offset = next;
127771
- }
127772
- if (!imageData || !ended) throw new DeviceScreenshotFailure({ message: "Incomplete PNG screenshot." });
127773
- return {
127774
- width,
127775
- height
127776
- };
127777
- }
127778
- const make$10 = Effect.fn("DeviceScreenshot.make")(function* () {
127779
- const http = yield* HttpClient.HttpClient;
127780
- return Effect.fn("DeviceScreenshot.capture")(function* (ready, session) {
127781
- const origin = yield* Effect.try(() => new URL(ready.hub.origin));
127782
- if (origin.protocol !== "http:" || origin.hostname !== "127.0.0.1" || !origin.port || origin.username || origin.password || origin.pathname !== "/" || origin.search || origin.hash) return yield* new DeviceScreenshotFailure({ message: "Invalid owned hub." });
127783
- const vendor = session.platform === "ios" ? "serve-sim" : "serve-emu";
127784
- const response = yield* http.execute(HttpClientRequest.post(`${origin.origin}/vendor/${vendor}/api/screenshot?device=${encodeURIComponent(session.deviceId)}`));
127785
- if (response.status !== 200) return yield* new DeviceScreenshotFailure({ message: "Screenshot rejected." });
127786
- let bytes = 0;
127787
- const chunks = [];
127788
- yield* response.stream.pipe(Stream.runForEach((chunk) => Effect.gen(function* () {
127789
- bytes += chunk.byteLength;
127790
- if (bytes > 8388608) return yield* new DeviceScreenshotFailure({ message: "Screenshot too large." });
127791
- chunks.push(chunk);
127792
- })));
127793
- const png = Buffer.concat(chunks, bytes);
127794
- return {
127795
- png,
127796
- ...yield* Effect.try(() => pngDimensions(png))
127797
- };
127798
- }, Effect.scoped, Effect.timeout(Duration.millis(SCREENSHOT_TIMEOUT_MS)), Effect.mapError(() => new DeviceOperationError({
127799
- operation: "screenshot",
127800
- reason: "request_failed",
127801
- cause: "Device screenshot could not be captured."
127802
- })));
127803
- });
127804
- var DeviceScreenshot = class extends Context.Service()("@p4code/cli/device/DeviceScreenshot") {};
127805
- const layer$6 = Layer.effect(DeviceScreenshot, make$10().pipe(Effect.map((capture) => ({ capture }))));
127806
- //#endregion
127807
- //#region src/device/DeviceCommandProxy.ts
127808
- var DeviceCommandProxyFailure = class extends Data.TaggedError("DeviceCommandProxyFailure") {};
127809
- const COMMAND_TIMEOUT_MS = 3e4;
127810
- const MAX_RESPONSE_BYTES$1 = 64 * 1024;
127811
- const Reply = Schema$1.Struct({
127812
- jsonrpc: Schema$1.Literal("2.0"),
127813
- id: Schema$1.String,
127814
- result: Schema$1.Struct({ ok: Schema$1.Boolean })
127815
- });
127816
- const make$9 = Effect.fn("DeviceCommandProxy.make")(function* () {
127817
- const http = yield* HttpClient.HttpClient;
127818
- const daemonSessions = /* @__PURE__ */ new WeakMap();
127819
- return Effect.fn("DeviceCommandProxy.execute")(function* (endpoint, session, payload) {
127820
- const input = yield* Schema$1.decodeUnknownEffect(DeviceCommandInput)(payload);
127821
- if (input.hostId !== session.hostId || input.deviceId !== session.deviceId) return yield* new DeviceCommandProxyFailure({ message: "Target mismatch" });
127822
- const origin = yield* Effect.try(() => new URL(endpoint.baseUrl));
127823
- if (origin.protocol !== "http:" || origin.hostname !== "127.0.0.1" || !origin.port || origin.username || origin.password || origin.pathname !== "/" || origin.search || origin.hash) return yield* new DeviceCommandProxyFailure({ message: "Invalid owned daemon" });
127824
- let daemonSession = daemonSessions.get(session);
127825
- if (!daemonSession) {
127826
- daemonSession = `p4-${NodeCrypto.randomUUID()}`;
127827
- daemonSessions.set(session, daemonSession);
127828
- }
127829
- const id = NodeCrypto.randomUUID();
127830
- const request = HttpClientRequest.post(`${origin.origin}/rpc`).pipe(HttpClientRequest.bodyJsonUnsafe({
127831
- jsonrpc: "2.0",
127832
- id,
127833
- method: "agent_device.command",
127834
- params: {
127835
- token: endpoint.token,
127836
- session: daemonSession,
127837
- command: input.command,
127838
- positionals: input.command === "press" ? [String(input.x), String(input.y)] : [input.text],
127839
- flags: session.platform === "ios" ? {
127840
- platform: "ios",
127841
- udid: session.deviceId
127842
- } : {
127843
- platform: "android",
127844
- serial: session.deviceId
127845
- }
127846
- }
127847
- }));
127848
- const response = yield* http.execute(request);
127849
- if (response.status !== 200) return yield* new DeviceCommandProxyFailure({ message: "Command rejected" });
127850
- let bytes = 0;
127851
- const body = yield* collectUint8StreamText({
127852
- stream: response.stream.pipe(Stream.mapEffect((chunk) => {
127853
- bytes += chunk.byteLength;
127854
- return bytes > MAX_RESPONSE_BYTES$1 ? Effect.fail(new DeviceCommandProxyFailure({ message: "Command response too large" })) : Effect.succeed(chunk);
127855
- })),
127856
- maxBytes: MAX_RESPONSE_BYTES$1
127857
- });
127858
- if (body.invalidUtf8 || body.truncated) return yield* new DeviceCommandProxyFailure({ message: "Invalid response" });
127859
- const reply = yield* Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(Reply))(body.text);
127860
- if (reply.id !== id || !reply.result.ok) return yield* new DeviceCommandProxyFailure({ message: "Command not acknowledged" });
127861
- return { ok: true };
127862
- }, Effect.scoped, Effect.timeout(Duration.millis(COMMAND_TIMEOUT_MS)), Effect.mapError(() => new DeviceOperationError({
127863
- operation: "command",
127864
- reason: "request_failed",
127865
- cause: "Device command could not be completed."
127866
- })));
127867
- });
127868
- var DeviceCommandProxy = class extends Context.Service()("@p4code/cli/device/DeviceCommandProxy") {};
127869
- const layer$5 = Layer.effect(DeviceCommandProxy, make$9().pipe(Effect.map((execute) => ({ execute }))));
127870
- //#endregion
127871
- //#region src/mcp/DeviceInvocation.ts
127872
- const isDeviceToolUnavailableError = Schema$1.is(DeviceToolUnavailableError);
127873
- const isDeviceActionUnavailableError = Schema$1.is(DeviceActionUnavailableError);
127874
- /** Internal bridge; tool payloads never choose thread identity or daemon credentials. */
127875
- const withDeviceInvocation = (execute) => Effect.gen(function* () {
127876
- const invocation = yield* McpInvocationContext;
127877
- const service = yield* DeviceService;
127878
- const lifetime = invocation.authorizationLifetime;
127879
- const denied = () => new DeviceToolUnavailableError({ reason: "Device command unavailable or authorization changed." });
127880
- if (!invocation.capabilities.has("devices") || !lifetime?.revocation || lifetime.revoked) return yield* denied();
127881
- 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()));
127882
- return yield* Effect.raceFirst(work, Deferred.await(lifetime.revocation).pipe(Effect.andThen(Effect.fail(denied()))));
127883
- });
127884
- const withDeviceSession = (target, execute) => withDeviceInvocation((service, threadId) => service.withAgentCommand({
127885
- hostId: target.hostId,
127886
- deviceId: target.deviceId,
127887
- threadId
127888
- }, execute));
127889
- //#endregion
127890
128246
  //#region src/mcp/toolkits/devices/tools.ts
127891
128247
  const DeviceCommandTool = Tool.make("device_command", {
127892
128248
  description: "Press explicit screen coordinates or type text into the focused field on a device already opened in this thread. Requires separate agent device consent and the exact host/device session. Coordinates are device screen coordinates. No arbitrary CLI commands or flags are accepted.",
@@ -128867,14 +129223,29 @@ const ThreadPairCreateTool = Tool.make("thread_pair_create", {
128867
129223
  Crypto.Crypto
128868
129224
  ]
128869
129225
  }).annotate(Tool.Title, "Create a Fusion pair").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
129226
+ const ThreadPairDetachTool = Tool.make("thread_pair_detach", {
129227
+ description: "Detach this agent session's active Fusion pair, stopping future automatic supervisor reviews while preserving both threads. The session must be the pair's implementer and must have created its supervisor through thread_spawn.",
129228
+ parameters: ThreadPairDetachInput,
129229
+ success: ThreadPairDetachResult,
129230
+ failure: ThreadControlToolError,
129231
+ dependencies: [
129232
+ McpInvocationContext,
129233
+ OrchestrationEngineService,
129234
+ ProjectionSnapshotQuery,
129235
+ Crypto.Crypto
129236
+ ]
129237
+ }).annotate(Tool.Title, "Detach Fusion pair").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
128870
129238
  const ThreadConfigureTool = Tool.make("thread_configure", {
128871
- description: "Change a thread's settings: title, model, permission mode, interaction mode, compression, and whether it may use subagents without asking. Omit threadId to configure this session's own thread; name one only if this session started it. Every field is optional and an omitted field is left alone; the settings actually changed come back in the result.",
129239
+ description: "Change a thread's settings: title, model, permission mode, interaction mode, compression, and whether it may use subagents without asking. Omit threadId to configure this session's own thread; name one only if this session started it. Supported model changes apply to the next turn, including automatic Fusion continuation. Started conversations cannot switch provider drivers or incompatible provider instances; such requests fail before any setting is changed. To use another provider, create a new thread with that selection (thread_spawn, optionally fusion: true) and preserve the current thread. Every field is optional and an omitted field is left alone; the settings actually changed come back in the result.",
128872
129240
  parameters: ThreadConfigureInput,
128873
129241
  success: ThreadConfigureResult,
128874
129242
  failure: ThreadControlToolError,
128875
129243
  dependencies: [
128876
129244
  McpInvocationContext,
128877
129245
  OrchestrationEngineService,
129246
+ ProjectionThreadRepository,
129247
+ ProjectionThreadSessionRepository,
129248
+ ProviderRegistry,
128878
129249
  Crypto.Crypto
128879
129250
  ]
128880
129251
  }).annotate(Tool.Title, "Configure a thread").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
@@ -128963,7 +129334,7 @@ const ThreadPlanUpdateTool = Tool.make("thread_plan_update", {
128963
129334
  Crypto.Crypto
128964
129335
  ]
128965
129336
  }).annotate(Tool.Title, "Update task phases").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
128966
- const ThreadToolkit = Toolkit.make(ThreadPlanUpdateTool, AskUserQuestionTool, ThreadSpawnTool, ThreadPairCreateTool, ThreadConfigureTool, ThreadSettleTool, ThreadCleanupTool, ThreadSnoozeTool, ThreadRenameTool, MemoryAppendTool, AssetCompressTool);
129337
+ const ThreadToolkit = Toolkit.make(ThreadPlanUpdateTool, AskUserQuestionTool, ThreadSpawnTool, ThreadPairCreateTool, ThreadPairDetachTool, ThreadConfigureTool, ThreadSettleTool, ThreadCleanupTool, ThreadSnoozeTool, ThreadRenameTool, MemoryAppendTool, AssetCompressTool);
128967
129338
  //#endregion
128968
129339
  //#region src/orchestration/pendingMcpUserInputs.ts
128969
129340
  /**
@@ -129290,10 +129661,69 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
129290
129661
  continuationMessageId
129291
129662
  };
129292
129663
  }),
129664
+ thread_pair_detach: (input) => Effect.gen(function* () {
129665
+ const invocation = yield* requireThreadCapability();
129666
+ const pair = ((yield* (yield* ProjectionSnapshotQuery).getCommandReadModel().pipe(Effect.mapError((cause) => new ThreadControlRejectedError({
129667
+ threadId: invocation.threadId,
129668
+ commandType: "thread-pair.detach",
129669
+ detail: `The active Fusion pair could not be read: ${cause.message}`
129670
+ })))).threadPairs ?? []).find((candidate) => candidate.id === input.pairId && candidate.detachedAt === null);
129671
+ if (pair === void 0) return yield* new ThreadControlRejectedError({
129672
+ threadId: invocation.threadId,
129673
+ commandType: "thread-pair.detach",
129674
+ detail: `Active Fusion pair '${input.pairId}' was not found.`
129675
+ });
129676
+ if (pair.implementerThreadId !== invocation.threadId) return yield* new ThreadControlRejectedError({
129677
+ threadId: invocation.threadId,
129678
+ commandType: "thread-pair.detach",
129679
+ detail: "This session is not the pair's implementer."
129680
+ });
129681
+ if (!invocation.controlThreadIds?.has(pair.watcherThreadId)) return yield* new ThreadControlRejectedError({
129682
+ threadId: invocation.threadId,
129683
+ commandType: "thread-pair.detach",
129684
+ detail: "This session did not create the pair's supervisor with thread_spawn."
129685
+ });
129686
+ const detachedAt = DateTime.formatIso(yield* DateTime.now);
129687
+ yield* dispatchControl({
129688
+ type: "thread-pair.detach",
129689
+ commandId: yield* newCommandId,
129690
+ pairId: pair.id,
129691
+ createdAt: detachedAt
129692
+ }, invocation.threadId);
129693
+ return {
129694
+ pairId: pair.id,
129695
+ implementerThreadId: pair.implementerThreadId,
129696
+ watcherThreadId: pair.watcherThreadId,
129697
+ detachedAt
129698
+ };
129699
+ }),
129293
129700
  thread_configure: (input) => Effect.gen(function* () {
129294
129701
  const { threadId } = yield* requireThreadControlTarget(input.threadId);
129295
129702
  const createdAt = DateTime.formatIso(yield* DateTime.now);
129296
129703
  const applied = [];
129704
+ if (input.modelSelection !== void 0) {
129705
+ const requested = input.modelSelection;
129706
+ const providers = yield* (yield* ProviderRegistry).getProviders;
129707
+ const target = providers.find((provider) => provider.instanceId === requested.instanceId);
129708
+ const rejectSelection = (detail) => new ThreadControlRejectedError({
129709
+ threadId,
129710
+ commandType: "thread.meta.update",
129711
+ detail
129712
+ });
129713
+ if (!target) return yield* rejectSelection(`Provider instance '${requested.instanceId}' is not configured.`);
129714
+ const session = yield* (yield* ProjectionThreadSessionRepository).getByThreadId({ threadId }).pipe(Effect.mapError((cause) => rejectSelection(cause.message)));
129715
+ if (Option.isSome(session)) {
129716
+ const thread = yield* (yield* ProjectionThreadRepository).getById({ threadId }).pipe(Effect.mapError((cause) => rejectSelection(cause.message)));
129717
+ if (Option.isSome(thread)) {
129718
+ const currentInstanceId = session.value.providerInstanceId ?? thread.value.modelSelection.instanceId;
129719
+ const current = providers.find((provider) => provider.instanceId === currentInstanceId);
129720
+ const instanceChanged = requested.instanceId !== currentInstanceId;
129721
+ const incompatible = instanceChanged && (!current || current.driver !== target.driver || !current.continuation || current.continuation.groupKey !== target.continuation?.groupKey);
129722
+ const requiresNewThread = (instanceChanged || requested.model !== thread.value.modelSelection.model) && (current?.requiresNewThreadForModelChange === true || target.requiresNewThreadForModelChange === true);
129723
+ if (incompatible || requiresNewThread) return yield* rejectSelection(`This conversation cannot switch to '${requested.model}' on '${requested.instanceId}'. Start a new thread with that provider and model, then enable Fusion there with the same supervisor settings. The current thread, checkout, history and Fusion pair are unchanged.`);
129724
+ }
129725
+ }
129726
+ }
129297
129727
  if (input.title !== void 0 || input.modelSelection !== void 0) {
129298
129728
  yield* dispatchControl({
129299
129729
  type: "thread.meta.update",
@@ -133081,7 +133511,7 @@ const make$5 = Effect.gen(function* () {
133081
133511
  const thread = yield* resolveThread(threadId);
133082
133512
  if (!thread) return yield* Effect.die(/* @__PURE__ */ new Error(`Thread '${threadId}' was not found in read model.`));
133083
133513
  const desiredRuntimeMode = thread.runtimeMode;
133084
- const requestedModelSelection = options?.modelSelection;
133514
+ const requestedModelSelection = options?.modelSelection ?? thread.modelSelection;
133085
133515
  const commandReadModel = yield* projectionSnapshotQuery.getCommandReadModel();
133086
133516
  const watchThreadIds = (commandReadModel.threadPairs ?? []).filter((pair) => pair.detachedAt === null && pair.watcherThreadId === threadId).map((pair) => pair.implementerThreadId);
133087
133517
  yield* Effect.forEach(watchThreadIds, (watchedThreadId) => grantActiveMcpWatchThread({
@@ -133100,7 +133530,7 @@ const make$5 = Effect.gen(function* () {
133100
133530
  method: "thread.turn.start",
133101
133531
  detail: `Thread '${threadId}' has an active provider session without a provider instance id.`
133102
133532
  });
133103
- const currentInstanceId = activeThreadSession !== null && activeSession !== void 0 && activeSession.providerInstanceId !== void 0 ? activeSession.providerInstanceId : thread.modelSelection.instanceId;
133533
+ const currentInstanceId = activeThreadSession !== null && activeSession !== void 0 && activeSession.providerInstanceId !== void 0 ? activeSession.providerInstanceId : thread.session?.providerInstanceId ?? thread.modelSelection.instanceId;
133104
133534
  const desiredModelSelection = requestedModelSelection ?? thread.modelSelection;
133105
133535
  const desiredInstanceId = desiredModelSelection.instanceId;
133106
133536
  const currentInfo = yield* providerService.getInstanceInfo(currentInstanceId).pipe(Effect.mapError(() => new ProviderAdapterRequestError({
@@ -133264,11 +133694,18 @@ const make$5 = Effect.gen(function* () {
133264
133694
  const thread = yield* resolveThread(input.threadId);
133265
133695
  if (!thread) return yield* Effect.die(/* @__PURE__ */ new Error(`Thread '${input.threadId}' was not found in read model.`));
133266
133696
  const hadActiveSession = thread.session !== null && thread.session.status !== "stopped";
133697
+ const modelForTurn = input.modelSelection ?? thread.modelSelection;
133267
133698
  yield* ensureSessionForThread(input.threadId, input.createdAt, {
133268
- ...input.modelSelection !== void 0 ? { modelSelection: input.modelSelection } : {},
133699
+ modelSelection: modelForTurn,
133269
133700
  pendingTurnStart: true
133270
133701
  });
133271
- if (input.modelSelection !== void 0) threadModelSelections.set(input.threadId, input.modelSelection);
133702
+ threadModelSelections.set(input.threadId, modelForTurn);
133703
+ if (!Equal.equals(thread.modelSelection, modelForTurn)) yield* orchestrationEngine.dispatch({
133704
+ type: "thread.meta.update",
133705
+ commandId: yield* serverCommandId("turn-model-selection"),
133706
+ threadId: input.threadId,
133707
+ modelSelection: modelForTurn
133708
+ });
133272
133709
  const normalizedInput = toNonEmptyProviderInput(input.messageText);
133273
133710
  const expandedInput = normalizedInput === void 0 ? void 0 : (yield* expandUserInvokedSkill({
133274
133711
  text: normalizedInput,
@@ -133326,16 +133763,6 @@ const make$5 = Effect.gen(function* () {
133326
133763
  ].join("\n\n");
133327
133764
  const providerHasStructuredQuestionSystemPrompt = activeSession?.provider === "claudeAgent" || activeSession?.provider === "codex";
133328
133765
  const inputWithStructuredQuestionPolicy = fusionInput !== void 0 && !providerHasStructuredQuestionSystemPrompt ? `${NON_SYSTEM_PROVIDER_STRUCTURED_USER_QUESTIONS}\n\n${fusionInput}` : fusionInput;
133329
- const sessionModelSwitch = activeSession === void 0 ? "in-session" : activeSession.providerInstanceId === void 0 ? yield* new ProviderAdapterRequestError({
133330
- provider: providerErrorLabel(activeSession.provider),
133331
- method: "thread.turn.start",
133332
- detail: `Active provider session '${activeSession.threadId}' is missing a provider instance id.`
133333
- }) : (yield* providerService.getCapabilities(activeSession.providerInstanceId)).sessionModelSwitch;
133334
- const requestedModelSelection = input.modelSelection ?? threadModelSelections.get(input.threadId) ?? thread.modelSelection;
133335
- const modelForTurn = sessionModelSwitch === "unsupported" && input.modelSelection === void 0 ? activeSession?.model !== void 0 ? {
133336
- ...requestedModelSelection,
133337
- model: activeSession.model
133338
- } : requestedModelSelection : requestedModelSelection;
133339
133766
  const compressMode = thread.compressMode;
133340
133767
  const hasSessionLevelRuleset = activeSession?.provider === "claudeAgent" || activeSession?.provider === "codex";
133341
133768
  const rebuildsRulesetEachTurn = activeSession?.provider === "codex";
@@ -133751,8 +134178,7 @@ const make$5 = Effect.gen(function* () {
133751
134178
  case "thread.runtime-mode-set": {
133752
134179
  const thread = yield* resolveThread(event.payload.threadId);
133753
134180
  if (!thread?.session || thread.session.status === "stopped") return;
133754
- const cachedModelSelection = threadModelSelections.get(event.payload.threadId);
133755
- yield* ensureSessionForThread(event.payload.threadId, event.occurredAt, cachedModelSelection !== void 0 ? { modelSelection: cachedModelSelection } : {});
134181
+ yield* ensureSessionForThread(event.payload.threadId, event.occurredAt);
133756
134182
  return;
133757
134183
  }
133758
134184
  case "thread.turn-start-requested":
@@ -136015,7 +136441,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
136015
136441
  sink,
136016
136442
  ...delegate ? { delegate } : {}
136017
136443
  });
136018
- return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$63(sink));
136444
+ return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$61(sink));
136019
136445
  })).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
136020
136446
  const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
136021
136447
  url: config.otlpMetricsUrl,
@@ -136043,7 +136469,7 @@ const SqliteError = Schema$1.Struct({
136043
136469
  const isSqliteError = Schema$1.is(SqliteError);
136044
136470
  var ServerInstanceAlreadyRunningError = class extends Schema$1.TaggedErrorClass()("ServerInstanceAlreadyRunningError", { stateDir: Schema$1.String }) {
136045
136471
  get message() {
136046
- return `A P4Code server is already using ${this.stateDir}. Stop it before starting another server with the same P4 home.`;
136472
+ return `A P4 Code server is already using ${this.stateDir}. Stop it before starting another server with the same P4 home.`;
136047
136473
  }
136048
136474
  };
136049
136475
  var ServerInstanceLockError = class extends Schema$1.TaggedErrorClass()("ServerInstanceLockError", {
@@ -136052,7 +136478,7 @@ var ServerInstanceLockError = class extends Schema$1.TaggedErrorClass()("ServerI
136052
136478
  cause: Schema$1.Defect()
136053
136479
  }) {
136054
136480
  get message() {
136055
- return `Failed to ${this.operation} P4Code server lock at ${this.lockPath}.`;
136481
+ return `Failed to ${this.operation} P4 Code server lock at ${this.lockPath}.`;
136056
136482
  }
136057
136483
  };
136058
136484
  const isSqliteBusy = (cause) => {
@@ -136387,31 +136813,31 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
136387
136813
  }
136388
136814
  }));
136389
136815
  const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReactorLive), Layer.provideMerge(ProviderRuntimeIngestionLive), Layer.provideMerge(ProviderCommandReactorLive), Layer.provideMerge(CheckpointReactorLive), Layer.provideMerge(ThreadDeletionReactorLive), Layer.provideMerge(FusionWatcherReactorLive), Layer.provideMerge(ScheduledTaskReactorLive), Layer.provideMerge(ThreadCompletionReactorLive), Layer.provideMerge(PullRequestSyncReactorLive), Layer.provideMerge(RuntimeReceiptBusLive));
136390
- const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$8));
136816
+ const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$6));
136391
136817
  const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
136392
136818
  const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
136393
- const VcsDriverRegistryLayerLive = layer$49.pipe(Layer.provide(layer$50));
136394
- const SourceControlProviderRegistryLayerLive = layer$35.pipe(Layer.provide(Layer.mergeAll(layer$43, layer$41, layer$39, layer$37)), Layer.provideMerge(layer$51), Layer.provideMerge(VcsDriverRegistryLayerLive));
136395
- const GitManagerLayerLive = layer$34.pipe(Layer.provideMerge(layer$44), Layer.provideMerge(layer$51), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$60));
136396
- const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$51));
136397
- const GitWorkflowLayerLive = layer$33.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
136398
- const SourceControlRepositoryServiceLayerLive = layer$9.pipe(Layer.provideMerge(layer$51), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
136399
- const ReviewLayerLive = layer$14.pipe(Layer.provideMerge(layer$51), Layer.provideMerge(VcsDriverRegistryLayerLive));
136400
- const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$50), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$15.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$16.pipe(Layer.provide(autoPullPolicyLayer), Layer.provide(GitWorkflowLayerLive))));
136401
- const PullRequestServiceLive = layer$27.pipe(Layer.provide(layer$28), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(layer$52));
136402
- const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$47), Layer.provideMerge(layer$48.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
136403
- const PortScannerLayerLive = layer$46.pipe(Layer.provide(layer$81));
136404
- const TerminalLayerLive = layer$45.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
136405
- const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$20), Layer.provideMerge(PortScannerLayerLive));
136406
- const WorkspaceEntriesLayerLive = layer$18.pipe(Layer.provide(layer$68));
136407
- const WorkspaceFileSystemLayerLive = layer$17.pipe(Layer.provide(layer$68), Layer.provide(WorkspaceEntriesLayerLive));
136819
+ const VcsDriverRegistryLayerLive = layer$47.pipe(Layer.provide(layer$48));
136820
+ const SourceControlProviderRegistryLayerLive = layer$33.pipe(Layer.provide(Layer.mergeAll(layer$41, layer$39, layer$37, layer$35)), Layer.provideMerge(layer$49), Layer.provideMerge(VcsDriverRegistryLayerLive));
136821
+ const GitManagerLayerLive = layer$32.pipe(Layer.provideMerge(layer$42), Layer.provideMerge(layer$49), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$58));
136822
+ const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$49));
136823
+ const GitWorkflowLayerLive = layer$31.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
136824
+ const SourceControlRepositoryServiceLayerLive = layer$7.pipe(Layer.provideMerge(layer$49), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
136825
+ const ReviewLayerLive = layer$12.pipe(Layer.provideMerge(layer$49), Layer.provideMerge(VcsDriverRegistryLayerLive));
136826
+ const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$48), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$13.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$14.pipe(Layer.provide(autoPullPolicyLayer), Layer.provide(GitWorkflowLayerLive))));
136827
+ const PullRequestServiceLive = layer$25.pipe(Layer.provide(layer$26), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(layer$50));
136828
+ const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$45), Layer.provideMerge(layer$46.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
136829
+ const PortScannerLayerLive = layer$44.pipe(Layer.provide(layer$81));
136830
+ const TerminalLayerLive = layer$43.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
136831
+ const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$18), Layer.provideMerge(PortScannerLayerLive));
136832
+ const WorkspaceEntriesLayerLive = layer$16.pipe(Layer.provide(layer$68));
136833
+ const WorkspaceFileSystemLayerLive = layer$15.pipe(Layer.provide(layer$68), Layer.provide(WorkspaceEntriesLayerLive));
136408
136834
  const WorkspaceLayerLive = Layer.mergeAll(layer$68, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
136409
- const ProjectFaviconResolverLayerLive = layer$64.pipe(Layer.provide(layer$68), Layer.provide(layer$65));
136835
+ const ProjectFaviconResolverLayerLive = layer$62.pipe(Layer.provide(layer$68), Layer.provide(layer$63));
136410
136836
  const AuthLayerLive = layer$110.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$114));
136411
136837
  const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
136412
- const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$26), Layer.provideMerge(Layer.mergeAll(PullRequestServiceLive, CheckpointingLayerLive, SourceControlProviderRegistryLayerLive)), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderAuthServiceLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$85)), Layer.provideMerge(layer$79), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(layer$59), Layer.provideMerge(Layer.mergeAll(layer$58, layer$70.pipe(Layer.provide(layer$81)), layer$6, layer$5)), Layer.provideMerge(layer$53), Layer.provideMerge(layer$54), Layer.provideMerge(layer$55), Layer.provideMerge(layer$56), Layer.provideMerge(layer$57)).pipe(Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$61), Layer.provideMerge(layer$89.pipe(Layer.provide(layer$114))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$80), Layer.provideMerge(layer$67), Layer.provideMerge(remoteComputerUseBindingsLayer.pipe(Layer.provide(layer$85))), Layer.provideMerge(layer$73), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$4.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$86, layer$22).pipe(Layer.provideMerge(layer$87), Layer.provideMerge(layer$88))))), Layer.provideMerge(layer$114));
136413
- const UsageLayerLive = layer$24.pipe(Layer.provide(layer$89.pipe(Layer.provide(layer$114))));
136414
- const RuntimeDependenciesLive = layer$23.pipe(Layer.provideMerge(RuntimeCoreDependenciesLive)).pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$13), Layer.provideMerge(layer$12), Layer.provideMerge(layer$11), Layer.provideMerge(layer$76), Layer.provideMerge(layer$78), Layer.provideMerge(layer$77), Layer.provide(layer$118));
136838
+ const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$24), Layer.provideMerge(Layer.mergeAll(PullRequestServiceLive, CheckpointingLayerLive, SourceControlProviderRegistryLayerLive)), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderAuthServiceLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$85)), Layer.provideMerge(layer$79), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(layer$57), Layer.provideMerge(Layer.mergeAll(layer$56, layer$70.pipe(Layer.provide(layer$81)), layer$66, layer$67)), Layer.provideMerge(layer$51), Layer.provideMerge(layer$52), Layer.provideMerge(layer$53), Layer.provideMerge(layer$54), Layer.provideMerge(layer$55)).pipe(Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$59), Layer.provideMerge(layer$89.pipe(Layer.provide(layer$114))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$80), Layer.provideMerge(layer$65), Layer.provideMerge(remoteComputerUseBindingsLayer.pipe(Layer.provide(layer$85))), Layer.provideMerge(layer$73), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$4.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$86, layer$20).pipe(Layer.provideMerge(layer$87), Layer.provideMerge(layer$88))))), Layer.provideMerge(layer$114));
136839
+ const UsageLayerLive = layer$22.pipe(Layer.provide(layer$89.pipe(Layer.provide(layer$114))));
136840
+ const RuntimeDependenciesLive = layer$21.pipe(Layer.provideMerge(RuntimeCoreDependenciesLive)).pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$11), Layer.provideMerge(layer$10), Layer.provideMerge(layer$9), Layer.provideMerge(layer$76), Layer.provideMerge(layer$78), Layer.provideMerge(layer$77), Layer.provide(layer$118));
136415
136841
  /**
136416
136842
  * Hub asset sync.
136417
136843
  *
@@ -136421,7 +136847,7 @@ const RuntimeDependenciesLive = layer$23.pipe(Layer.provideMerge(RuntimeCoreDepe
136421
136847
  */
136422
136848
  const AssetSyncLive = layer$83.pipe(Layer.provideMerge(layer$84), Layer.provideMerge(layer$85));
136423
136849
  const RuntimeServicesLive = layer$69.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
136424
- const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(pullRequestHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer$3.pipe(Layer.provide(layer$7)), layer$66, layer).pipe(Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionThreadRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$65), Layer.provide(layer$26), Layer.provide(PullRequestServiceLive), Layer.provide(layer$21), Layer.provide(layer$74), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
136850
+ const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(pullRequestHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer$3.pipe(Layer.provide(layer$5)), layer$64, layer).pipe(Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionThreadRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$63), Layer.provide(layer$24), Layer.provide(PullRequestServiceLive), Layer.provide(layer$19), Layer.provide(layer$74), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
136425
136851
  const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
136426
136852
  const config = yield* ServerConfig$1;
136427
136853
  yield* fixPath();
@@ -136464,7 +136890,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
136464
136890
  cause,
136465
136891
  servePort: configured.servePort
136466
136892
  }))) : Effect.void)) : Layer.empty;
136467
- const fullyProvisionedServerLayer = Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer, layer$1, layer$2).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$52));
136893
+ const fullyProvisionedServerLayer = Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer, layer$1, layer$2).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$50));
136468
136894
  return Layer.unwrap(Effect.gen(function* () {
136469
136895
  yield* acquireServerInstanceLock(config.stateDir);
136470
136896
  return fullyProvisionedServerLayer;
@@ -136477,8 +136903,8 @@ const runServerCommand = (flags, options) => Effect.gen(function* () {
136477
136903
  const config = yield* resolveServerConfig(flags, yield* GlobalFlag.LogLevel, options);
136478
136904
  return yield* runServer.pipe(Effect.provideService(ServerConfig$1, config));
136479
136905
  });
136480
- const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4Code server."), Command.withHandler((flags) => runServerCommand(flags)));
136481
- const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4Code server without opening a browser and print headless pairing details."), Command.withHandler((flags) => runServerCommand(flags, {
136906
+ const startCommand = Command.make("start", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4 Code server."), Command.withHandler((flags) => runServerCommand(flags)));
136907
+ const serveCommand = Command.make("serve", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4 Code server without opening a browser and print headless pairing details."), Command.withHandler((flags) => runServerCommand(flags, {
136482
136908
  startupPresentation: "headless",
136483
136909
  forceAutoBootstrapProjectFromCwd: false
136484
136910
  })));
@@ -136873,16 +137299,16 @@ const reconcileService = Effect.fn("cli.service.reconcile")(function* () {
136873
137299
  const LAUNCH_AGENT_LOGIN_NOTE = "This runs as a login item, so it starts when you log in. For an unattended machine, enable automatic login in System Settings › Users & Groups.";
136874
137300
  function formatReconcileSuccess(input) {
136875
137301
  return [
136876
- `${input.previouslyInstalled ? "Updated" : "Installed"} P4Code service with @p4code/cli@${input.cliVersion}.`,
137302
+ `${input.previouslyInstalled ? "Updated" : "Installed"} P4 Code service with @p4code/cli@${input.cliVersion}.`,
136877
137303
  `Logs: ${input.plan.logPath}`,
136878
137304
  ...input.platform === "darwin" && !input.previouslyInstalled ? [LAUNCH_AGENT_LOGIN_NOTE] : []
136879
137305
  ].join("\n");
136880
137306
  }
136881
137307
  function formatServiceStatus(status, cliVersion, lastUpdate) {
136882
- if (!status.supported) return "P4Code service\n Status: unavailable on this machine\n Supported on: Linux with systemd, macOS with launchd";
136883
- if (!status.installed) return "P4Code service\n Status: not installed\n Next: Run `p4c service install`.";
137308
+ if (!status.supported) return "P4 Code service\n Status: unavailable on this machine\n Supported on: Linux with systemd, macOS with launchd";
137309
+ if (!status.installed) return "P4 Code service\n Status: not installed\n Next: Run `p4c service install`.";
136884
137310
  return [
136885
- "P4Code service",
137311
+ "P4 Code service",
136886
137312
  ` Status: ${status.current ? `installed · @p4code/cli@${cliVersion}` : "needs an update or repair"}`,
136887
137313
  ` Unit: ${status.unitPath}`,
136888
137314
  ` Data: ${status.baseDir}`,
@@ -136935,10 +137361,10 @@ const serviceInstallCommand = Command.make("install", {
136935
137361
  ...projectLocationFlags,
136936
137362
  tailscaleServe: tailscaleServeFlag,
136937
137363
  tailscaleServePort: tailscaleServePortFlag
136938
- }).pipe(Command.withDescription("Install P4Code as a background service for this user."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
137364
+ }).pipe(Command.withDescription("Install P4 Code as a background service for this user."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
136939
137365
  const result = yield* reconcileService();
136940
137366
  if (!result.changed) {
136941
- yield* Console.log(`P4Code service is already installed with @p4code/cli@${version$1}.`);
137367
+ yield* Console.log(`P4 Code service is already installed with @p4code/cli@${version$1}.`);
136942
137368
  return;
136943
137369
  }
136944
137370
  yield* Console.log(formatReconcileSuccess({
@@ -136965,7 +137391,7 @@ const serviceUpdateCommand = Command.make("update", projectLocationFlags).pipe(C
136965
137391
  });
136966
137392
  }
136967
137393
  if (!outcome.result.changed) {
136968
- yield* Console.log(`Restarted the P4Code service on @p4code/cli@${version$1}.`);
137394
+ yield* Console.log(`Restarted the P4 Code service on @p4code/cli@${version$1}.`);
136969
137395
  return;
136970
137396
  }
136971
137397
  yield* Console.log(formatReconcileSuccess({
@@ -136975,9 +137401,9 @@ const serviceUpdateCommand = Command.make("update", projectLocationFlags).pipe(C
136975
137401
  platform: yield* HostProcessPlatform
136976
137402
  }));
136977
137403
  }))));
136978
- const serviceUninstallCommand = Command.make("uninstall", projectLocationFlags).pipe(Command.withDescription("Stop and remove the P4Code background service."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
137404
+ const serviceUninstallCommand = Command.make("uninstall", projectLocationFlags).pipe(Command.withDescription("Stop and remove the P4 Code background service."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
136979
137405
  const removed = yield* (yield* BootService).uninstall;
136980
- yield* Console.log(removed ? "Removed the P4Code service." : "P4Code service is not installed.");
137406
+ yield* Console.log(removed ? "Removed the P4 Code service." : "P4 Code service is not installed.");
136981
137407
  }))));
136982
137408
  /**
136983
137409
  * Restart without rewriting the unit.
@@ -136991,11 +137417,11 @@ const serviceUninstallCommand = Command.make("uninstall", projectLocationFlags).
136991
137417
  const serviceRestartCommand = Command.make("restart", projectLocationFlags).pipe(Command.withDescription("Restart the background service without changing its configuration."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
136992
137418
  const service = yield* BootService;
136993
137419
  if (!(yield* service.status).installed) {
136994
- yield* Console.error("P4Code service is not installed. Install it with: p4c service install");
137420
+ yield* Console.error("P4 Code service is not installed. Install it with: p4c service install");
136995
137421
  return;
136996
137422
  }
136997
137423
  yield* service.restart;
136998
- yield* Console.log("Restarted the P4Code service.");
137424
+ yield* Console.log("Restarted the P4 Code service.");
136999
137425
  }))));
137000
137426
  /**
137001
137427
  * Install a newer CLI, then point the service at it.
@@ -137030,7 +137456,7 @@ const serviceSelfUpdateCommand = Command.make("self-update", {
137030
137456
  });
137031
137457
  yield* Console.log(`Service now runs @p4code/cli@${installed}.`);
137032
137458
  }))));
137033
- const serviceStatusCommand = Command.make("status", projectLocationFlags).pipe(Command.withDescription("Show whether the P4Code background service is installed."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
137459
+ const serviceStatusCommand = Command.make("status", projectLocationFlags).pipe(Command.withDescription("Show whether the P4 Code background service is installed."), Command.withHandler((flags) => runServiceCommand(flags, Effect.gen(function* () {
137034
137460
  const status = yield* (yield* BootService).status;
137035
137461
  const recorded = yield* readServiceUpdateState(status.baseDir);
137036
137462
  yield* Console.log(formatServiceStatus(status, version$1, Option.match(recorded, {
@@ -137042,18 +137468,18 @@ Effect.gen(function* () {
137042
137468
  const { supported, installed, current } = yield* (yield* BootService).status;
137043
137469
  if (!supported) return false;
137044
137470
  if (installed && current) {
137045
- yield* Console.log("P4Code is already set up to run in the background on this machine.");
137471
+ yield* Console.log("P4 Code is already set up to run in the background on this machine.");
137046
137472
  return true;
137047
137473
  }
137048
137474
  if (!(yield* Prompt.run(Prompt.confirm({
137049
- message: installed ? "The installed P4Code service needs an update or repair. Update it now?" : "Run P4Code in the background whenever this machine boots? It stays reachable to your other devices over the network.",
137475
+ message: installed ? "The installed P4 Code service needs an update or repair. Update it now?" : "Run P4 Code in the background whenever this machine boots? It stays reachable to your other devices over the network.",
137050
137476
  initial: true
137051
137477
  })))) return false;
137052
137478
  const result = yield* reconcileService();
137053
137479
  if (result.changed) yield* Console.log(`Background service ${result.previouslyInstalled ? "updated" : "installed"}. Logs: ${result.plan.logPath}`);
137054
137480
  return true;
137055
137481
  });
137056
- const serviceCommand = Command.make("service").pipe(Command.withDescription("Manage the P4Code background service."), Command.withSubcommands([
137482
+ const serviceCommand = Command.make("service").pipe(Command.withDescription("Manage the P4 Code background service."), Command.withSubcommands([
137057
137483
  serviceInstallCommand,
137058
137484
  serviceUninstallCommand,
137059
137485
  serviceUpdateCommand,
@@ -137090,7 +137516,7 @@ const reportUpdateAvailable = Effect.gen(function* () {
137090
137516
  * conflict we chose. Taking a name nothing else claims deletes the problem
137091
137517
  * rather than managing it.
137092
137518
  */
137093
- const makeCli = () => Command.make("p4c", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4Code server."), Command.withHandler((flags) => runServerCommand(flags)), Command.withSubcommands([
137519
+ const makeCli = () => Command.make("p4c", { ...sharedServerCommandFlags }).pipe(Command.withDescription("Run the P4 Code server."), Command.withHandler((flags) => runServerCommand(flags)), Command.withSubcommands([
137094
137520
  startCommand,
137095
137521
  serveCommand,
137096
137522
  agentsCommand,