@p4code/cli 0.5.4 → 0.5.6
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 +1782 -418
- package/dist/client/assets/{DiffPanel-CRatYkMr.js → DiffPanel-D8eBc-aG.js} +2 -2
- package/dist/client/assets/{FilePreviewPanel-Bj9oMAni.js → FilePreviewPanel-BTSTI93L.js} +2 -2
- package/dist/client/assets/{PreviewPanel-BXk62FYk.js → PreviewPanel-BRylbqHA.js} +2 -2
- package/dist/client/assets/{PullRequestCodeTab-BftwY9yH.js → PullRequestCodeTab-Y9jgYJZq.js} +2 -2
- package/dist/client/assets/{fileCommentAnnotations-2ZSnwBCq.js → fileCommentAnnotations-pNlR9x0T.js} +2 -2
- package/dist/client/assets/{index-CUbaiNT9.js → index-GS5A_LTK.js} +188 -175
- package/dist/client/assets/{index-Bb0jNtjG.css → index-H5w-6k_f.css} +1 -1
- package/dist/client/assets/previewAssetResource-DGdLZELv.js +48 -0
- package/dist/client/assets/{renderFileChildren-Bl4eZEU1.js → renderFileChildren-DPpHhKCk.js} +2 -2
- package/dist/client/assets/{toggle-group-CfOTk4Pb.js → toggle-group-JCyq--Le.js} +2 -2
- package/dist/client/index.html +3 -3
- package/package.json +1 -1
- package/dist/client/assets/previewAssetResource-Bmv-dii0.js +0 -48
package/dist/bin.mjs
CHANGED
|
@@ -19,8 +19,11 @@ import "effect/LogLevel";
|
|
|
19
19
|
import * as Path$1 from "effect/Path";
|
|
20
20
|
import * as Schema$1 from "effect/Schema";
|
|
21
21
|
import * as NodePath from "node:path";
|
|
22
|
+
import { isAbsolute } from "node:path";
|
|
22
23
|
import * as NodeChildProcess from "node:child_process";
|
|
24
|
+
import { spawn } from "node:child_process";
|
|
23
25
|
import * as NodeFS from "node:fs";
|
|
26
|
+
import { constants } from "node:fs";
|
|
24
27
|
import * as DateTime from "effect/DateTime";
|
|
25
28
|
import * as Duration from "effect/Duration";
|
|
26
29
|
import * as Option from "effect/Option";
|
|
@@ -42,6 +45,7 @@ import * as Config from "effect/Config";
|
|
|
42
45
|
import * as References from "effect/References";
|
|
43
46
|
import * as HttpServerRequest$1 from "effect/unstable/http/HttpServerRequest";
|
|
44
47
|
import * as NodeCrypto from "node:crypto";
|
|
48
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
45
49
|
import * as Encoding from "effect/Encoding";
|
|
46
50
|
import * as Result$1 from "effect/Result";
|
|
47
51
|
import * as Crypto from "effect/Crypto";
|
|
@@ -57,6 +61,7 @@ import * as Cause from "effect/Cause";
|
|
|
57
61
|
import * as Exit from "effect/Exit";
|
|
58
62
|
import * as NodeReadline from "node:readline";
|
|
59
63
|
import * as NodeFSP from "node:fs/promises";
|
|
64
|
+
import { access } from "node:fs/promises";
|
|
60
65
|
import * as Clock from "effect/Clock";
|
|
61
66
|
import * as NodeStream from "@effect/platform-node/NodeStream";
|
|
62
67
|
import * as NodeHttp from "node:http";
|
|
@@ -148,7 +153,7 @@ const closeServer = (server) => {
|
|
|
148
153
|
* NetService - Service tag for startup networking helpers.
|
|
149
154
|
*/
|
|
150
155
|
var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
|
|
151
|
-
const make$
|
|
156
|
+
const make$116 = () => {
|
|
152
157
|
/**
|
|
153
158
|
* Returns true when a TCP server can bind to {host, port}.
|
|
154
159
|
* `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
|
|
@@ -257,10 +262,10 @@ const make$115 = () => {
|
|
|
257
262
|
})
|
|
258
263
|
};
|
|
259
264
|
};
|
|
260
|
-
const layer$
|
|
265
|
+
const layer$119 = Layer.sync(NetService, make$116);
|
|
261
266
|
//#endregion
|
|
262
267
|
//#region package.json
|
|
263
|
-
var version$1 = "0.5.
|
|
268
|
+
var version$1 = "0.5.6";
|
|
264
269
|
//#endregion
|
|
265
270
|
//#region src/config.ts
|
|
266
271
|
/**
|
|
@@ -281,8 +286,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
|
|
|
281
286
|
/** @deprecated Import and use `layerTest` from this module. */
|
|
282
287
|
static layerTest = (cwd, baseDirOrPrefix) => layerTest$4(cwd, baseDirOrPrefix);
|
|
283
288
|
};
|
|
284
|
-
const make$
|
|
285
|
-
const layer$
|
|
289
|
+
const make$115 = (config) => ServerConfig$1.of(config);
|
|
290
|
+
const layer$118 = (config) => Layer.succeed(ServerConfig$1, make$115(config));
|
|
286
291
|
const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
|
|
287
292
|
const { join } = yield* Path$1.Path;
|
|
288
293
|
const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
|
|
@@ -3719,9 +3724,21 @@ const OrchestrationThreadPairGate = Schema$1.Struct({
|
|
|
3719
3724
|
awaitingWatcherSince: Schema$1.NullOr(IsoDateTime),
|
|
3720
3725
|
updatedAt: IsoDateTime
|
|
3721
3726
|
});
|
|
3727
|
+
const FusionReviewPolicy = Schema$1.Struct({
|
|
3728
|
+
mode: Schema$1.Literals(["phase", "risk-and-final"]),
|
|
3729
|
+
maxAutomaticReviews: PositiveInt.pipe(Schema$1.withDecodingDefault(Effect.succeed(4))),
|
|
3730
|
+
maxCorrectionRounds: NonNegativeInt.pipe(Schema$1.withDecodingDefault(Effect.succeed(2)))
|
|
3731
|
+
});
|
|
3732
|
+
const FusionReviewExperiment = Schema$1.Struct({
|
|
3733
|
+
policy: FusionReviewPolicy,
|
|
3734
|
+
lastMessageSequence: Schema$1.optionalKey(NonNegativeInt),
|
|
3735
|
+
automaticReviews: NonNegativeInt,
|
|
3736
|
+
correctionRounds: NonNegativeInt
|
|
3737
|
+
});
|
|
3722
3738
|
/** Persisted relationship between two otherwise ordinary threads. */
|
|
3723
3739
|
const OrchestrationThreadPair = Schema$1.Struct({
|
|
3724
3740
|
id: ThreadPairId,
|
|
3741
|
+
reviewExperiment: Schema$1.optionalKey(Schema$1.NullOr(FusionReviewExperiment)),
|
|
3725
3742
|
implementerThreadId: ThreadId,
|
|
3726
3743
|
watcherThreadId: ThreadId,
|
|
3727
3744
|
lastReviewedImplementerSequence: NonNegativeInt,
|
|
@@ -4245,6 +4262,7 @@ const ThreadPairCreateCommand = Schema$1.Struct({
|
|
|
4245
4262
|
implementerThreadId: ThreadId,
|
|
4246
4263
|
watcherThreadId: ThreadId,
|
|
4247
4264
|
continuationMessageId: Schema$1.optional(MessageId),
|
|
4265
|
+
reviewPolicy: Schema$1.optionalKey(Schema$1.NullOr(FusionReviewPolicy)),
|
|
4248
4266
|
roundCap: Schema$1.optional(NonNegativeInt),
|
|
4249
4267
|
gateTimeoutMs: Schema$1.optional(NonNegativeInt),
|
|
4250
4268
|
createdAt: IsoDateTime
|
|
@@ -4770,6 +4788,7 @@ const ThreadPairCreatedPayload$1 = Schema$1.Struct({
|
|
|
4770
4788
|
lastReviewedImplementerSequence: NonNegativeInt,
|
|
4771
4789
|
activationTurnId: Schema$1.optional(Schema$1.NullOr(TurnId)),
|
|
4772
4790
|
continuationMessageId: Schema$1.optional(MessageId),
|
|
4791
|
+
reviewPolicy: Schema$1.optionalKey(Schema$1.NullOr(FusionReviewPolicy)),
|
|
4773
4792
|
roundCap: Schema$1.optional(NonNegativeInt),
|
|
4774
4793
|
gateTimeoutMs: Schema$1.optional(NonNegativeInt),
|
|
4775
4794
|
createdAt: IsoDateTime
|
|
@@ -7809,6 +7828,7 @@ const TaskProgressPayload = Schema$1.Struct({
|
|
|
7809
7828
|
usage: Schema$1.optional(Schema$1.Unknown),
|
|
7810
7829
|
lastToolName: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
|
|
7811
7830
|
toolUseId: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
|
|
7831
|
+
model: Schema$1.optional(TrimmedNonEmptyStringSchema$1),
|
|
7812
7832
|
subagentType: Schema$1.optional(TrimmedNonEmptyStringSchema$1)
|
|
7813
7833
|
});
|
|
7814
7834
|
const TaskCompletedPayload = Schema$1.Struct({
|
|
@@ -8824,7 +8844,11 @@ const DeviceHostSummary = Schema$1.Struct({
|
|
|
8824
8844
|
label: TrimmedNonEmptyString.check(Schema$1.isMaxLength(MAX_HOST_LABEL_LENGTH)),
|
|
8825
8845
|
platforms: Schema$1.Array(DevicePlatformAvailability),
|
|
8826
8846
|
hubInstalled: Schema$1.Boolean,
|
|
8827
|
-
agentDeviceInstalled: Schema$1.Boolean
|
|
8847
|
+
agentDeviceInstalled: Schema$1.Boolean,
|
|
8848
|
+
automation: Schema$1.optional(Schema$1.Struct({
|
|
8849
|
+
provider: Schema$1.Literals(["apple-xcode", "xcodebuildmcp"]),
|
|
8850
|
+
detail: Schema$1.String
|
|
8851
|
+
}))
|
|
8828
8852
|
});
|
|
8829
8853
|
/**
|
|
8830
8854
|
* Lifecycle of the helper processes on a host. Tools are installed on first
|
|
@@ -10153,6 +10177,10 @@ const ServerSettings = Schema$1.Struct({
|
|
|
10153
10177
|
* smaller; off is the rollback if a pair misbehaves.
|
|
10154
10178
|
*/
|
|
10155
10179
|
enableOptimizedFusionPromptDelivery: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
10180
|
+
/** Local daily measurements and weekly recommendations; never starts agent turns. */
|
|
10181
|
+
enableFusionObservation: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
10182
|
+
/** Experimental policy captured by new pairs; null preserves existing behavior. */
|
|
10183
|
+
fusionReviewPolicy: Schema$1.NullOr(FusionReviewPolicy).pipe(Schema$1.withDecodingDefault(Effect.succeed(null))),
|
|
10156
10184
|
/**
|
|
10157
10185
|
* Whether the board offers the scoping agent: the Scope action on a task and
|
|
10158
10186
|
* the panel that drafts a new one by interview.
|
|
@@ -10359,6 +10387,8 @@ const ServerSettingsPatch = Schema$1.Struct({
|
|
|
10359
10387
|
enableRootCauseBeforeFix: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10360
10388
|
enableUnpromptedSubagents: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10361
10389
|
enableOptimizedFusionPromptDelivery: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10390
|
+
enableFusionObservation: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10391
|
+
fusionReviewPolicy: Schema$1.optionalKey(Schema$1.NullOr(FusionReviewPolicy)),
|
|
10362
10392
|
enableScopingAgent: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10363
10393
|
enablePlanPhase: Schema$1.optionalKey(Schema$1.Boolean),
|
|
10364
10394
|
writeGeneratedSkillsToRepo: Schema$1.optionalKey(Schema$1.Boolean),
|
|
@@ -13571,6 +13601,45 @@ const ComputerUseDeviceTarget = {
|
|
|
13571
13601
|
deviceId: DeviceId,
|
|
13572
13602
|
leaseId: DeviceId
|
|
13573
13603
|
};
|
|
13604
|
+
const DeviceElementRef = TrimmedNonEmptyString.check(Schema$1.isMaxLength(128));
|
|
13605
|
+
const DeviceGesture = {
|
|
13606
|
+
direction: Schema$1.Literals([
|
|
13607
|
+
"up",
|
|
13608
|
+
"down",
|
|
13609
|
+
"left",
|
|
13610
|
+
"right"
|
|
13611
|
+
]),
|
|
13612
|
+
distance: Schema$1.optional(Schema$1.Number.check(Schema$1.isGreaterThan(0), Schema$1.isLessThanOrEqualTo(1)))
|
|
13613
|
+
};
|
|
13614
|
+
const ComputerUseDeviceAction = Schema$1.Union([
|
|
13615
|
+
Schema$1.Struct({
|
|
13616
|
+
action: Schema$1.Literal("tap"),
|
|
13617
|
+
elementRef: DeviceElementRef
|
|
13618
|
+
}),
|
|
13619
|
+
Schema$1.Struct({
|
|
13620
|
+
action: Schema$1.Literal("type_text"),
|
|
13621
|
+
elementRef: DeviceElementRef,
|
|
13622
|
+
text: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(16e3)),
|
|
13623
|
+
replaceExisting: Schema$1.optional(Schema$1.Boolean)
|
|
13624
|
+
}),
|
|
13625
|
+
Schema$1.Struct({
|
|
13626
|
+
action: Schema$1.Literal("swipe"),
|
|
13627
|
+
withinElementRef: DeviceElementRef,
|
|
13628
|
+
...DeviceGesture
|
|
13629
|
+
}),
|
|
13630
|
+
Schema$1.Struct({
|
|
13631
|
+
action: Schema$1.Literal("drag"),
|
|
13632
|
+
elementRef: DeviceElementRef,
|
|
13633
|
+
...DeviceGesture
|
|
13634
|
+
}),
|
|
13635
|
+
Schema$1.Struct({
|
|
13636
|
+
action: Schema$1.Literal("batch"),
|
|
13637
|
+
steps: Schema$1.Array(Schema$1.Struct({
|
|
13638
|
+
action: Schema$1.Literal("tap"),
|
|
13639
|
+
elementRef: DeviceElementRef
|
|
13640
|
+
})).check(Schema$1.isMinLength(1), Schema$1.isMaxLength(100))
|
|
13641
|
+
})
|
|
13642
|
+
]);
|
|
13574
13643
|
const ComputerUseDeviceOperation = Schema$1.Union([
|
|
13575
13644
|
Schema$1.Struct({ method: Schema$1.Literal("list") }),
|
|
13576
13645
|
Schema$1.Struct({
|
|
@@ -13585,7 +13654,18 @@ const ComputerUseDeviceOperation = Schema$1.Union([
|
|
|
13585
13654
|
"screenshot",
|
|
13586
13655
|
"close"
|
|
13587
13656
|
]),
|
|
13588
|
-
...ComputerUseDeviceTarget
|
|
13657
|
+
...ComputerUseDeviceTarget,
|
|
13658
|
+
sinceScreenHash: Schema$1.optional(TrimmedNonEmptyString)
|
|
13659
|
+
}),
|
|
13660
|
+
Schema$1.Struct({
|
|
13661
|
+
method: Schema$1.Literal("semantic"),
|
|
13662
|
+
...ComputerUseDeviceTarget,
|
|
13663
|
+
action: ComputerUseDeviceAction
|
|
13664
|
+
}),
|
|
13665
|
+
Schema$1.Struct({
|
|
13666
|
+
method: Schema$1.Literal("recording"),
|
|
13667
|
+
...ComputerUseDeviceTarget,
|
|
13668
|
+
action: Schema$1.Literals(["start", "stop"])
|
|
13589
13669
|
}),
|
|
13590
13670
|
Schema$1.Struct({
|
|
13591
13671
|
method: Schema$1.Literal("command"),
|
|
@@ -13697,6 +13777,7 @@ const WS_METHODS = {
|
|
|
13697
13777
|
serverGetProcessDiagnostics: "server.getProcessDiagnostics",
|
|
13698
13778
|
serverGetProcessResourceHistory: "server.getProcessResourceHistory",
|
|
13699
13779
|
serverSignalProcess: "server.signalProcess",
|
|
13780
|
+
threadHandoff: "thread.handoff",
|
|
13700
13781
|
btwAsk: "btw.ask",
|
|
13701
13782
|
btwCancel: "btw.cancel",
|
|
13702
13783
|
pullRequestsList: "pullRequests.list",
|
|
@@ -14340,6 +14421,14 @@ const WsServerGetProviderUsageRpc = Rpc.make(WS_METHODS.serverGetProviderUsage,
|
|
|
14340
14421
|
success: Schema$1.Struct({ report: Schema$1.String }),
|
|
14341
14422
|
error: Schema$1.Union([TextGenerationError, EnvironmentAuthorizationError])
|
|
14342
14423
|
});
|
|
14424
|
+
const WsThreadHandoffRpc = Rpc.make(WS_METHODS.threadHandoff, {
|
|
14425
|
+
payload: Schema$1.Struct({ threadId: ThreadId }),
|
|
14426
|
+
success: Schema$1.Struct({
|
|
14427
|
+
projectId: ProjectId,
|
|
14428
|
+
text: Schema$1.String
|
|
14429
|
+
}),
|
|
14430
|
+
error: Schema$1.Union([TextGenerationError, EnvironmentAuthorizationError])
|
|
14431
|
+
});
|
|
14343
14432
|
const WsBtwAskRpc = Rpc.make(WS_METHODS.btwAsk, {
|
|
14344
14433
|
payload: BtwAskInput,
|
|
14345
14434
|
success: BtwAskResult,
|
|
@@ -14800,7 +14889,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
|
|
|
14800
14889
|
error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
|
|
14801
14890
|
stream: true
|
|
14802
14891
|
});
|
|
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);
|
|
14892
|
+
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, WsThreadHandoffRpc, 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);
|
|
14804
14893
|
//#endregion
|
|
14805
14894
|
//#region ../../packages/shared/src/oauthScope.ts
|
|
14806
14895
|
const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
|
|
@@ -14946,7 +15035,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
14946
15035
|
//#endregion
|
|
14947
15036
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
14948
15037
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
14949
|
-
const make$
|
|
15038
|
+
const make$114 = Effect.gen(function* () {
|
|
14950
15039
|
const config = yield* ServerConfig$1;
|
|
14951
15040
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
14952
15041
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -14964,7 +15053,7 @@ const make$113 = Effect.gen(function* () {
|
|
|
14964
15053
|
};
|
|
14965
15054
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
14966
15055
|
});
|
|
14967
|
-
const layer$
|
|
15056
|
+
const layer$117 = Layer.effect(EnvironmentAuthPolicy, make$114);
|
|
14968
15057
|
//#endregion
|
|
14969
15058
|
//#region src/persistence/Errors.ts
|
|
14970
15059
|
function summarizeSchemaIssue(issue) {
|
|
@@ -15145,7 +15234,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
15145
15234
|
cause
|
|
15146
15235
|
});
|
|
15147
15236
|
}
|
|
15148
|
-
const make$
|
|
15237
|
+
const make$113 = Effect.gen(function* () {
|
|
15149
15238
|
const sql = yield* SqlClient.SqlClient;
|
|
15150
15239
|
const createSessionRow = SqlSchema.void({
|
|
15151
15240
|
Request: CreateAuthSessionInput,
|
|
@@ -15279,7 +15368,7 @@ const make$112 = Effect.gen(function* () {
|
|
|
15279
15368
|
setLastConnectedAt
|
|
15280
15369
|
};
|
|
15281
15370
|
});
|
|
15282
|
-
const layer$
|
|
15371
|
+
const layer$116 = Layer.effect(AuthSessionRepository, make$113);
|
|
15283
15372
|
//#endregion
|
|
15284
15373
|
//#region src/auth/ServerSecretStore.ts
|
|
15285
15374
|
const secretStoreErrorContext = {
|
|
@@ -15421,11 +15510,11 @@ const makeForDirectory = Effect.fn("ServerSecretStore.makeForDirectory")(functio
|
|
|
15421
15510
|
remove
|
|
15422
15511
|
});
|
|
15423
15512
|
});
|
|
15424
|
-
const make$
|
|
15513
|
+
const make$112 = Effect.gen(function* () {
|
|
15425
15514
|
const config = yield* ServerConfig$1;
|
|
15426
15515
|
return yield* makeForDirectory(config.secretsDir);
|
|
15427
15516
|
});
|
|
15428
|
-
const layer$
|
|
15517
|
+
const layer$115 = Layer.effect(ServerSecretStore, make$112);
|
|
15429
15518
|
//#endregion
|
|
15430
15519
|
//#region src/auth/SessionStore.ts
|
|
15431
15520
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -15663,7 +15752,7 @@ function toAuthClientSession(input) {
|
|
|
15663
15752
|
current: false
|
|
15664
15753
|
};
|
|
15665
15754
|
}
|
|
15666
|
-
const make$
|
|
15755
|
+
const make$111 = Effect.gen(function* () {
|
|
15667
15756
|
const crypto = yield* Crypto.Crypto;
|
|
15668
15757
|
const serverConfig = yield* ServerConfig$1;
|
|
15669
15758
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -15978,7 +16067,7 @@ const make$110 = Effect.gen(function* () {
|
|
|
15978
16067
|
markDisconnected
|
|
15979
16068
|
});
|
|
15980
16069
|
});
|
|
15981
|
-
const layer$
|
|
16070
|
+
const layer$114 = Layer.effect(SessionStore, make$111).pipe(Layer.provideMerge(layer$116));
|
|
15982
16071
|
//#endregion
|
|
15983
16072
|
//#region src/persistence/AuthPairingLinks.ts
|
|
15984
16073
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -16039,7 +16128,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
16039
16128
|
cause
|
|
16040
16129
|
});
|
|
16041
16130
|
}
|
|
16042
|
-
const make$
|
|
16131
|
+
const make$110 = Effect.gen(function* () {
|
|
16043
16132
|
const sql = yield* SqlClient.SqlClient;
|
|
16044
16133
|
const createPairingLinkRow = SqlSchema.void({
|
|
16045
16134
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -16174,7 +16263,7 @@ const make$109 = Effect.gen(function* () {
|
|
|
16174
16263
|
getByCredential
|
|
16175
16264
|
};
|
|
16176
16265
|
});
|
|
16177
|
-
const layer$
|
|
16266
|
+
const layer$113 = Layer.effect(AuthPairingLinkRepository, make$110);
|
|
16178
16267
|
//#endregion
|
|
16179
16268
|
//#region src/auth/PairingGrantStore.ts
|
|
16180
16269
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -16269,7 +16358,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
16269
16358
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
16270
16359
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
16271
16360
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
16272
|
-
const make$
|
|
16361
|
+
const make$109 = Effect.gen(function* () {
|
|
16273
16362
|
const crypto = yield* Crypto.Crypto;
|
|
16274
16363
|
const config = yield* ServerConfig$1;
|
|
16275
16364
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -16467,7 +16556,7 @@ const make$108 = Effect.gen(function* () {
|
|
|
16467
16556
|
consume
|
|
16468
16557
|
});
|
|
16469
16558
|
});
|
|
16470
|
-
const layer$
|
|
16559
|
+
const layer$112 = Layer.effect(PairingGrantStore, make$109).pipe(Layer.provideMerge(layer$113));
|
|
16471
16560
|
//#endregion
|
|
16472
16561
|
//#region src/persistence/DatabaseSnapshot.ts
|
|
16473
16562
|
/**
|
|
@@ -16599,6 +16688,11 @@ const discardDatabaseSnapshot = Effect.fn("discardDatabaseSnapshot")(function* (
|
|
|
16599
16688
|
yield* fs.remove(paths.stagingPath, { force: true });
|
|
16600
16689
|
});
|
|
16601
16690
|
//#endregion
|
|
16691
|
+
//#region src/persistence/Migrations/059_FusionReviewExperiment.ts
|
|
16692
|
+
var _059_FusionReviewExperiment_default = Effect.gen(function* () {
|
|
16693
|
+
yield* (yield* SqlClient.SqlClient)`ALTER TABLE thread_pairs ADD COLUMN review_experiment_json TEXT`;
|
|
16694
|
+
});
|
|
16695
|
+
//#endregion
|
|
16602
16696
|
//#region src/persistence/Migrations/001_OrchestrationEvents.ts
|
|
16603
16697
|
var _001_OrchestrationEvents_default = Effect.gen(function* () {
|
|
16604
16698
|
const sql = yield* SqlClient.SqlClient;
|
|
@@ -18770,6 +18864,11 @@ const migrationEntries = [
|
|
|
18770
18864
|
58,
|
|
18771
18865
|
"HubActivityOutbound",
|
|
18772
18866
|
_058_HubActivityOutbound_default
|
|
18867
|
+
],
|
|
18868
|
+
[
|
|
18869
|
+
59,
|
|
18870
|
+
"FusionReviewExperiment",
|
|
18871
|
+
_059_FusionReviewExperiment_default
|
|
18773
18872
|
]
|
|
18774
18873
|
];
|
|
18775
18874
|
const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -19798,7 +19897,7 @@ function parseBearerToken(request) {
|
|
|
19798
19897
|
const token = header.slice(7).trim();
|
|
19799
19898
|
return token.length > 0 ? token : null;
|
|
19800
19899
|
}
|
|
19801
|
-
const make$
|
|
19900
|
+
const make$108 = Effect.gen(function* () {
|
|
19802
19901
|
const policy = yield* EnvironmentAuthPolicy;
|
|
19803
19902
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
19804
19903
|
const sessions = yield* SessionStore;
|
|
@@ -19993,9 +20092,9 @@ const make$107 = Effect.gen(function* () {
|
|
|
19993
20092
|
issueStartupPairingUrl
|
|
19994
20093
|
});
|
|
19995
20094
|
});
|
|
19996
|
-
const layer$
|
|
19997
|
-
const storageLayer = Layer.mergeAll(layer$
|
|
19998
|
-
const runtimeLayer = layer$
|
|
20095
|
+
const layer$111 = Layer.effect(EnvironmentAuth, make$108).pipe(Layer.provideMerge(layer$112), Layer.provideMerge(layer$114), Layer.provideMerge(layer$117));
|
|
20096
|
+
const storageLayer = Layer.mergeAll(layer$115, layerConfig);
|
|
20097
|
+
const runtimeLayer = layer$111.pipe(Layer.provideMerge(storageLayer));
|
|
19999
20098
|
//#endregion
|
|
20000
20099
|
//#region ../../packages/shared/src/Struct.ts
|
|
20001
20100
|
function deepMerge(current, patch) {
|
|
@@ -21843,7 +21942,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
|
|
|
21843
21942
|
}
|
|
21844
21943
|
return yield* Effect.gen(function* () {
|
|
21845
21944
|
return yield* run(yield* EnvironmentAuth);
|
|
21846
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$
|
|
21945
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$118(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
21847
21946
|
});
|
|
21848
21947
|
const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
|
|
21849
21948
|
const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
|
|
@@ -21989,7 +22088,7 @@ const DEFAULT_LIMITS = {
|
|
|
21989
22088
|
windowMillis: FAILURE_WINDOW_MS$1,
|
|
21990
22089
|
blockMillis: BLOCK_DURATION_MS
|
|
21991
22090
|
};
|
|
21992
|
-
const make$
|
|
22091
|
+
const make$107 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
21993
22092
|
const state = yield* Ref.make(initialThrottleState);
|
|
21994
22093
|
return HubAuthThrottle.of({
|
|
21995
22094
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -22003,7 +22102,7 @@ const make$106 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_L
|
|
|
22003
22102
|
})
|
|
22004
22103
|
});
|
|
22005
22104
|
});
|
|
22006
|
-
const layer$
|
|
22105
|
+
const layer$110 = Layer.effect(HubAuthThrottle, make$107());
|
|
22007
22106
|
//#endregion
|
|
22008
22107
|
//#region src/hub/HubAuth.ts
|
|
22009
22108
|
/**
|
|
@@ -22771,7 +22870,7 @@ const TaskRepositoryLive = Layer.effect(TaskRepository, makeTaskRepository);
|
|
|
22771
22870
|
//#region src/hub/HubClientRevocations.ts
|
|
22772
22871
|
var HubClientRevocations = class extends Context.Service()("@p4code/cli/hub/HubClientRevocations") {};
|
|
22773
22872
|
/** Coalesced invalidations carry no identity or credential; consumers recheck durable state. */
|
|
22774
|
-
const layer$
|
|
22873
|
+
const layer$109 = Layer.effect(HubClientRevocations, Effect.gen(function* () {
|
|
22775
22874
|
const changes = yield* PubSub.sliding(1);
|
|
22776
22875
|
yield* Effect.addFinalizer(() => PubSub.shutdown(changes));
|
|
22777
22876
|
return HubClientRevocations.of({
|
|
@@ -23009,7 +23108,7 @@ const hubClientPreflight = Effect.gen(function* () {
|
|
|
23009
23108
|
}
|
|
23010
23109
|
});
|
|
23011
23110
|
});
|
|
23012
|
-
const layer$
|
|
23111
|
+
const layer$108 = Layer.mergeAll(Layer.empty, ...Object.keys(CLIENT_ROUTES).map((path) => HttpRouter.add("OPTIONS", path, hubClientPreflight)));
|
|
23013
23112
|
const HUB_TUNNEL_MAX_FRAME_PAYLOAD_BYTES = 64 * 1024;
|
|
23014
23113
|
const HUB_TUNNEL_MAX_MESSAGE_BYTES = 128 * 1024 * 1024;
|
|
23015
23114
|
const HUB_TUNNEL_FRAME_MAGIC = 1345606705;
|
|
@@ -23296,7 +23395,7 @@ var HubTunnelConnectorBudget = class {
|
|
|
23296
23395
|
const HUB_TUNNEL_RETIRE_TIMEOUT_MS = 1e4;
|
|
23297
23396
|
var HubTunnelUnavailable = class extends Data.TaggedError("HubTunnelUnavailable") {};
|
|
23298
23397
|
var HubTunnelRegistry = class extends Context.Service()("@p4code/cli/hub/HubTunnelRegistry") {};
|
|
23299
|
-
const layer$
|
|
23398
|
+
const layer$107 = Layer.effect(HubTunnelRegistry, Effect.gen(function* () {
|
|
23300
23399
|
const config = yield* HubConfig;
|
|
23301
23400
|
const lock = yield* Semaphore.make(1);
|
|
23302
23401
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -23549,7 +23648,7 @@ const makeHubClientSocketTickets = Effect.gen(function* () {
|
|
|
23549
23648
|
};
|
|
23550
23649
|
});
|
|
23551
23650
|
var HubClientSocketTickets = class extends Context.Service()("@p4code/cli/hub/HubClientSocketTickets") {};
|
|
23552
|
-
const layer$
|
|
23651
|
+
const layer$106 = Layer.effect(HubClientSocketTickets, makeHubClientSocketTickets);
|
|
23553
23652
|
//#endregion
|
|
23554
23653
|
//#region src/hub/HubClientLease.ts
|
|
23555
23654
|
/** Other Hub processes sharing the database are observed within this interval. */
|
|
@@ -23705,7 +23804,7 @@ const socketTicket = handle$1(Effect.gen(function* () {
|
|
|
23705
23804
|
}
|
|
23706
23805
|
}));
|
|
23707
23806
|
}), "client-route");
|
|
23708
|
-
const layer$
|
|
23807
|
+
const layer$105 = Layer.mergeAll(layer$108, HttpRouter.add("POST", "/v1/clients/me/socket-ticket", withHubClientCors(socketTicket)), HttpRouter.add("POST", "/v1/client-enrollments", issue$1), HttpRouter.add("POST", "/v1/client-enrollments/exchange", withHubClientCors(exchange$1)), HttpRouter.add("GET", "/v1/clients/me", withHubClientCors(identity$2)), HttpRouter.add("GET", "/v1/clients/me/events", withHubClientCors(events)), HttpRouter.add("DELETE", "/v1/clients/me", withHubClientCors(signOut)), HttpRouter.add("POST", "/v1/clients/revoke", revoke));
|
|
23709
23808
|
//#endregion
|
|
23710
23809
|
//#region src/hub/HubPushTokenProtection.ts
|
|
23711
23810
|
const KEY_NAME = "hub-push-token-encryption-v1";
|
|
@@ -23985,12 +24084,12 @@ const persistHubAgentActivity = Effect.fn("HubNotificationActivity.persist")(fun
|
|
|
23985
24084
|
var HubSecretStoreUnavailable = class extends Data.TaggedError("HubSecretStoreUnavailable") {};
|
|
23986
24085
|
const HUB_SECRETS_SUFFIX = ".secrets";
|
|
23987
24086
|
/** Dedicated sibling directory per Hub database; no environment configuration is consulted. */
|
|
23988
|
-
const make$
|
|
24087
|
+
const make$106 = Effect.gen(function* () {
|
|
23989
24088
|
const config = yield* HubConfig;
|
|
23990
24089
|
if (!(yield* Path$1.Path).isAbsolute(config.dbPath)) return yield* Effect.fail(new HubSecretStoreUnavailable({ message: "Hub secret storage requires an absolute database path." }));
|
|
23991
24090
|
return yield* makeForDirectory(`${config.dbPath}${HUB_SECRETS_SUFFIX}`);
|
|
23992
24091
|
});
|
|
23993
|
-
const layer$
|
|
24092
|
+
const layer$104 = Layer.effect(ServerSecretStore, make$106);
|
|
23994
24093
|
//#endregion
|
|
23995
24094
|
//#region src/hub/HubNotificationRoutes.ts
|
|
23996
24095
|
const MAX_NOTIFICATION_BODY_BYTES = 16 * 1024;
|
|
@@ -24034,7 +24133,7 @@ const makeRoutes = Effect.gen(function* () {
|
|
|
24034
24133
|
}))));
|
|
24035
24134
|
});
|
|
24036
24135
|
/** Launch-only composition: isolated Hub HTTP tests need no filesystem credential store. */
|
|
24037
|
-
const layer$
|
|
24136
|
+
const layer$103 = Layer.unwrap(makeRoutes).pipe(Layer.provide(layer$104));
|
|
24038
24137
|
//#endregion
|
|
24039
24138
|
//#region src/hub/HubApnsCredentials.ts
|
|
24040
24139
|
const HUB_APNS_CREDENTIAL_SECRET = "hub-apns-credentials-v1";
|
|
@@ -24605,7 +24704,7 @@ const MAX_APNS_REQUEST_BYTES = 4096;
|
|
|
24605
24704
|
const CLEANUP_TIMEOUT_MS$1 = 1e3;
|
|
24606
24705
|
const MAX_REQUEST_BYTES$2 = 8 * 1024;
|
|
24607
24706
|
const MAX_RESPONSE_BYTES$8 = 16 * 1024;
|
|
24608
|
-
const REQUEST_TIMEOUT_MS$
|
|
24707
|
+
const REQUEST_TIMEOUT_MS$7 = 8e3;
|
|
24609
24708
|
const MAX_AUTH_CHARS = 8192;
|
|
24610
24709
|
const unavailable$6 = () => ({
|
|
24611
24710
|
outcome: "retry",
|
|
@@ -24650,7 +24749,7 @@ const sendHubApns = Effect.fn("HubPushTransport.apns")(function* (input) {
|
|
|
24650
24749
|
finish(unavailable$6());
|
|
24651
24750
|
return;
|
|
24652
24751
|
}
|
|
24653
|
-
timer = setTimeout(() => finish(unavailable$6()), REQUEST_TIMEOUT_MS$
|
|
24752
|
+
timer = setTimeout(() => finish(unavailable$6()), REQUEST_TIMEOUT_MS$7);
|
|
24654
24753
|
session = NodeHttp2.connect(input.sandbox ? "https://api.sandbox.push.apple.com" : "https://api.push.apple.com", { maxHeaderListPairs: 32 });
|
|
24655
24754
|
session.on("error", () => finish(unavailable$6()));
|
|
24656
24755
|
session.on("close", () => finish(unavailable$6()));
|
|
@@ -24705,7 +24804,7 @@ const sendHubFcm = Effect.fn("HubPushTransport.fcm")(function* (input, fetcher =
|
|
|
24705
24804
|
const abort = () => owner.abort();
|
|
24706
24805
|
signal.addEventListener("abort", abort, { once: true });
|
|
24707
24806
|
if (signal.aborted) owner.abort();
|
|
24708
|
-
const timeout = setTimeout(abort, REQUEST_TIMEOUT_MS$
|
|
24807
|
+
const timeout = setTimeout(abort, REQUEST_TIMEOUT_MS$7);
|
|
24709
24808
|
let reader;
|
|
24710
24809
|
try {
|
|
24711
24810
|
const response = await fetcher(`https://fcm.googleapis.com/v1/projects/${input.projectId}/messages:send`, {
|
|
@@ -24746,7 +24845,7 @@ const sendHubFcm = Effect.fn("HubPushTransport.fcm")(function* (input, fetcher =
|
|
|
24746
24845
|
}
|
|
24747
24846
|
},
|
|
24748
24847
|
catch: () => unavailable$6()
|
|
24749
|
-
}).pipe(Effect.timeout(REQUEST_TIMEOUT_MS$
|
|
24848
|
+
}).pipe(Effect.timeout(REQUEST_TIMEOUT_MS$7), Effect.catch(() => Effect.succeed(unavailable$6())));
|
|
24750
24849
|
});
|
|
24751
24850
|
//#endregion
|
|
24752
24851
|
//#region src/hub/HubNotificationRuntime.ts
|
|
@@ -24777,10 +24876,10 @@ const makeHubNotificationProvider = Effect.fn("HubNotificationRuntime.provider")
|
|
|
24777
24876
|
});
|
|
24778
24877
|
});
|
|
24779
24878
|
const runHubNotificationSchedule = (batch) => batch.pipe(Effect.asVoid, Effect.catch(() => Effect.logWarning("Hub notification delivery unavailable.")), Effect.repeat(Schedule.spaced(Duration.millis(HUB_NOTIFICATION_INTERVAL_MS))));
|
|
24780
|
-
const layer$
|
|
24879
|
+
const layer$102 = Layer.effectDiscard(Effect.gen(function* () {
|
|
24781
24880
|
const batch = yield* makeHubNotificationDelivery(yield* makeHubNotificationProvider());
|
|
24782
24881
|
yield* runHubNotificationSchedule(batch()).pipe(Effect.forkScoped);
|
|
24783
|
-
})).pipe(Layer.provide(layer$
|
|
24882
|
+
})).pipe(Layer.provide(layer$104));
|
|
24784
24883
|
const HUB_RETIREMENT_TIMEOUT_MS = 1e4;
|
|
24785
24884
|
const HUB_RETIREMENT_CLAIM_MS = 3e4;
|
|
24786
24885
|
const HUB_RETIREMENT_TTL_MS = 1440 * 60 * 1e3;
|
|
@@ -24947,10 +25046,10 @@ const HUB_RETIREMENT_INTERVAL_MS = 5e3;
|
|
|
24947
25046
|
/** One bounded batch per tick; persisted due times control retries, never an in-memory retry loop. */
|
|
24948
25047
|
const runHubRetirementSchedule = (batch) => batch.pipe(Effect.asVoid, Effect.catch(() => Effect.logWarning("Hub retirement delivery unavailable.")), Effect.repeat(Schedule.spaced(Duration.millis(HUB_RETIREMENT_INTERVAL_MS))));
|
|
24949
25048
|
/** Secret store remains private to notification runtime rather than becoming a general Hub dependency. */
|
|
24950
|
-
const layer$
|
|
25049
|
+
const layer$101 = Layer.effectDiscard(Effect.gen(function* () {
|
|
24951
25050
|
const batch = yield* makeHubPushRetirementDelivery(yield* makeHubRetirementProvider());
|
|
24952
25051
|
yield* runHubRetirementSchedule(batch()).pipe(Effect.forkScoped);
|
|
24953
|
-
})).pipe(Layer.provide(layer$
|
|
25052
|
+
})).pipe(Layer.provide(layer$104));
|
|
24954
25053
|
/** One bounded keyset page; callers resume the receipt and restart from null after a full sweep. */
|
|
24955
25054
|
const reconcileHubPushRegistrations = Effect.fn("HubPushReconciliation.page")(function* (afterClientId = null) {
|
|
24956
25055
|
const sql = yield* SqlClient.SqlClient;
|
|
@@ -24993,7 +25092,7 @@ const sweepHubPushRegistrations = Effect.fn("HubPushReconciliation.sweep")(funct
|
|
|
24993
25092
|
};
|
|
24994
25093
|
});
|
|
24995
25094
|
/** Scoped schedule prevents overlapping sweeps and cancels both page work and waiting on shutdown. */
|
|
24996
|
-
const layer$
|
|
25095
|
+
const layer$100 = Layer.effectDiscard(Effect.gen(function* () {
|
|
24997
25096
|
yield* sweepHubPushRegistrations(reconcileHubPushRegistrations).pipe(Effect.catch(() => Effect.logWarning("Hub notification reconciliation unavailable.")), Effect.repeat(Schedule.spaced(Duration.millis(HUB_PUSH_RECONCILIATION_INTERVAL_MS))), Effect.forkScoped);
|
|
24998
25097
|
}));
|
|
24999
25098
|
//#endregion
|
|
@@ -25024,7 +25123,7 @@ const hubMdxHost = Effect.gen(function* () {
|
|
|
25024
25123
|
}
|
|
25025
25124
|
});
|
|
25026
25125
|
}).pipe(Effect.catch(() => Effect.succeed(HttpServerResponse.empty({ status: 503 }))));
|
|
25027
|
-
const layer$
|
|
25126
|
+
const layer$99 = Layer.mergeAll(HttpRouter.add("GET", "/mdx-host.html", hubMdxHost), HttpRouter.add("GET", "/mdx-jsx-runtime.js", hubMdxHost), HttpRouter.add("GET", "/assets/:file", hubMdxHost));
|
|
25028
25127
|
//#endregion
|
|
25029
25128
|
//#region ../../packages/shared/src/hubAssetGrant.ts
|
|
25030
25129
|
/** Managed assets retain the environment's signed grant root for relative preview resources. */
|
|
@@ -25109,7 +25208,7 @@ const makeHubClientAssetGrants = Effect.gen(function* () {
|
|
|
25109
25208
|
};
|
|
25110
25209
|
});
|
|
25111
25210
|
var HubClientAssetGrants = class extends Context.Service()("@p4code/cli/hub/HubClientAssetGrants") {};
|
|
25112
|
-
const layer$
|
|
25211
|
+
const layer$98 = Layer.effect(HubClientAssetGrants, makeHubClientAssetGrants);
|
|
25113
25212
|
//#endregion
|
|
25114
25213
|
//#region src/hub/HubTunnelHttpRequestProducer.ts
|
|
25115
25214
|
/** Consumes the ingress request lazily under its stream producer; transport admission owns frame copies. */
|
|
@@ -25411,7 +25510,7 @@ const writeHubTunnelNativeResponse = Effect.fn("HubTunnelNativeResponse.write")(
|
|
|
25411
25510
|
//#region src/hub/HubTunnelPublished.ts
|
|
25412
25511
|
const MAX_STREAM_ID$1 = 4294967295;
|
|
25413
25512
|
var HubTunnelPublished = class extends Context.Service()("@p4code/cli/hub/HubTunnelPublished") {};
|
|
25414
|
-
const layer$
|
|
25513
|
+
const layer$97 = Layer.effect(HubTunnelPublished, Effect.gen(function* () {
|
|
25415
25514
|
const registry = yield* HubTunnelRegistry;
|
|
25416
25515
|
const entries = /* @__PURE__ */ new Map();
|
|
25417
25516
|
const current = (lease) => Effect.gen(function* () {
|
|
@@ -25597,7 +25696,7 @@ const hubTunnelHttpRoute = Effect.gen(function* () {
|
|
|
25597
25696
|
const response = yield* authenticatedRoute;
|
|
25598
25697
|
return HttpServerResponse.setHeaders(response, cors);
|
|
25599
25698
|
});
|
|
25600
|
-
const layer$
|
|
25699
|
+
const layer$96 = HttpRouter.add("*", `${HUB_TUNNEL_HTTP_PATH}/*`, hubTunnelHttpRoute);
|
|
25601
25700
|
//#endregion
|
|
25602
25701
|
//#region src/hub/HubAssetRoutes.ts
|
|
25603
25702
|
const MAX_GRANT_BODY_BYTES = 8192;
|
|
@@ -25657,7 +25756,7 @@ const hubAssetRoute = Effect.gen(function* () {
|
|
|
25657
25756
|
}
|
|
25658
25757
|
}))));
|
|
25659
25758
|
});
|
|
25660
|
-
const layer$
|
|
25759
|
+
const layer$95 = Layer.mergeAll(HttpRouter.add("POST", "/v1/clients/me/asset-grant", issue), HttpRouter.add("*", `${HUB_ASSET_PATH}/*`, hubAssetRoute));
|
|
25661
25760
|
//#endregion
|
|
25662
25761
|
//#region src/hub/HubComputerUseIdentity.ts
|
|
25663
25762
|
/** A server identity is not a helper identity or a client pairing credential. */
|
|
@@ -25745,7 +25844,7 @@ const readBody = Effect.fn("hub.computerUse.readBody")(function* (request) {
|
|
|
25745
25844
|
return (yield* request.stream.pipe(Stream.runFoldEffect(() => Buffer.alloc(0), (body, chunk) => body.byteLength + chunk.byteLength > MAX_REQUEST_BYTES$1 ? Effect.fail(new HubComputerUseRoutesFailure({ message: "Computer Use enrollment body exceeds limit" })) : Effect.succeed(Buffer.concat([body, chunk]))))).toString("utf8");
|
|
25746
25845
|
});
|
|
25747
25846
|
/** Server-to-server delegation only. A Hub identity does not authenticate an ordinary environment client. */
|
|
25748
|
-
const layer$
|
|
25847
|
+
const layer$94 = Layer.unwrap(Effect.gen(function* () {
|
|
25749
25848
|
const enrollments = makeHubComputerUseEnrollments(yield* HubConfig);
|
|
25750
25849
|
const handle = Effect.fn("hub.computerUse.handle")(function* (operation) {
|
|
25751
25850
|
const environmentId = yield* authenticateHubComputerUseServer();
|
|
@@ -26554,7 +26653,7 @@ const hubTunnelConnectorRoute = Effect.gen(function* () {
|
|
|
26554
26653
|
status: 503,
|
|
26555
26654
|
headers: { "cache-control": "no-store" }
|
|
26556
26655
|
}))));
|
|
26557
|
-
const layer$
|
|
26656
|
+
const layer$93 = HttpRouter.add("GET", HUB_TUNNEL_CONNECTOR_PATH, hubTunnelConnectorRoute);
|
|
26558
26657
|
const TICKET_PATTERN = /^[a-f0-9]{64}$/;
|
|
26559
26658
|
const MAX_TICKETED_URL_CHARS = 8512;
|
|
26560
26659
|
/** Remove only Hub transport authentication; retain environment query bytes and order exactly. */
|
|
@@ -26745,7 +26844,7 @@ const hubTunnelClientSocketRoute = Effect.gen(function* () {
|
|
|
26745
26844
|
}
|
|
26746
26845
|
return unavailable$5();
|
|
26747
26846
|
})));
|
|
26748
|
-
const layer$
|
|
26847
|
+
const layer$92 = HttpRouter.add("GET", `${HUB_TUNNEL_CLIENT_SOCKET_PATH}/*`, hubTunnelClientSocketRoute);
|
|
26749
26848
|
//#endregion
|
|
26750
26849
|
//#region src/hub/HubHttpServer.ts
|
|
26751
26850
|
/**
|
|
@@ -27242,8 +27341,8 @@ const releaseFeedLeaseRoute = HttpRouter.add("DELETE", "/feed/lease", respondToH
|
|
|
27242
27341
|
return HttpServerResponse.empty({ status: 204 });
|
|
27243
27342
|
})));
|
|
27244
27343
|
/** Provide around HttpRouter.serve so request fibers share these process-owned services. */
|
|
27245
|
-
const routingServices = Layer.mergeAll(layer$
|
|
27246
|
-
const layer$
|
|
27344
|
+
const routingServices = Layer.mergeAll(layer$109, layer$106, layer$98, layer$97).pipe(Layer.provideMerge(layer$107));
|
|
27345
|
+
const layer$91 = Layer.mergeAll(layer$96, layer$95, layer$99, layer$93, layer$92, layer$105, layer$94, healthRoute, identityRoute, listTasksRoute, getTaskRoute, createTaskRoute, putTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute, listFeedSourcesRoute, upsertFeedSourceRoute, deleteFeedSourceRoute, listFeedRoute, putFeedArticleRoute, putFeedEngagementRoute, markFeedReadRoute, cleanupFeedRoute, setFeedRefreshedAtRoute, acquireFeedLeaseRoute, renewFeedLeaseRoute, releaseFeedLeaseRoute).pipe(Layer.provideMerge(layer$109), Layer.provideMerge(layer$106), Layer.provideMerge(layer$98));
|
|
27247
27346
|
//#endregion
|
|
27248
27347
|
//#region src/hub/Migrations/001_Tasks.ts
|
|
27249
27348
|
/**
|
|
@@ -27931,7 +28030,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
|
|
|
27931
28030
|
});
|
|
27932
28031
|
if (isRemoteReachableHost(config.host)) yield* Effect.logWarning("Hub is reachable beyond loopback. The bearer token is the only control — repeated auth failures are not rate limited.", { host: config.host });
|
|
27933
28032
|
}));
|
|
27934
|
-
const makeHubLayer = HttpRouter.serve(Layer.mergeAll(layer$
|
|
28033
|
+
const makeHubLayer = HttpRouter.serve(Layer.mergeAll(layer$91, layer$103)).pipe(Layer.provideMerge(routingServices), Layer.provideMerge(layer$101), Layer.provideMerge(layer$102), Layer.provideMerge(layer$100), Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$110), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
|
|
27935
28034
|
const runHub = Layer.launch(makeHubLayer);
|
|
27936
28035
|
//#endregion
|
|
27937
28036
|
//#region src/atomicWrite.ts
|
|
@@ -28062,7 +28161,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
28062
28161
|
}
|
|
28063
28162
|
return Object.is(current, defaults) ? void 0 : current;
|
|
28064
28163
|
}
|
|
28065
|
-
const make$
|
|
28164
|
+
const make$105 = Effect.gen(function* () {
|
|
28066
28165
|
const { settingsPath } = yield* ServerConfig$1;
|
|
28067
28166
|
const fs = yield* FileSystem.FileSystem;
|
|
28068
28167
|
const pathService = yield* Path$1.Path;
|
|
@@ -28284,7 +28383,7 @@ const make$104 = Effect.gen(function* () {
|
|
|
28284
28383
|
}
|
|
28285
28384
|
};
|
|
28286
28385
|
});
|
|
28287
|
-
const layer$
|
|
28386
|
+
const layer$90 = Layer.effect(ServerSettingsService, make$105);
|
|
28288
28387
|
//#endregion
|
|
28289
28388
|
//#region src/pathExpansion.ts
|
|
28290
28389
|
/**
|
|
@@ -28946,7 +29045,7 @@ function claudeEntryFromRegistration(registration) {
|
|
|
28946
29045
|
};
|
|
28947
29046
|
}
|
|
28948
29047
|
var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
|
|
28949
|
-
const make$
|
|
29048
|
+
const make$104 = Effect.gen(function* () {
|
|
28950
29049
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
28951
29050
|
const path = yield* Path$1.Path;
|
|
28952
29051
|
const services = yield* Effect.context();
|
|
@@ -29013,7 +29112,7 @@ const make$103 = Effect.gen(function* () {
|
|
|
29013
29112
|
removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
|
|
29014
29113
|
};
|
|
29015
29114
|
});
|
|
29016
|
-
const layer$
|
|
29115
|
+
const layer$89 = Layer.effect(ClaudeMcpFiles, make$104);
|
|
29017
29116
|
Layer.succeed(ClaudeMcpFiles, {
|
|
29018
29117
|
readUser: Effect.succeed([]),
|
|
29019
29118
|
readUserAt: () => Effect.succeed([]),
|
|
@@ -29151,7 +29250,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
|
|
|
29151
29250
|
const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
|
|
29152
29251
|
var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
|
|
29153
29252
|
const registryError = (detail) => new McpRegistryError({ detail });
|
|
29154
|
-
const make$
|
|
29253
|
+
const make$103 = Effect.gen(function* () {
|
|
29155
29254
|
const config = yield* ServerConfig$1;
|
|
29156
29255
|
const secrets = yield* ServerSecretStore;
|
|
29157
29256
|
const http = yield* HttpClient.HttpClient;
|
|
@@ -29471,7 +29570,7 @@ const make$102 = Effect.gen(function* () {
|
|
|
29471
29570
|
accessTokenFor
|
|
29472
29571
|
};
|
|
29473
29572
|
});
|
|
29474
|
-
const layer$
|
|
29573
|
+
const layer$88 = Layer.effect(McpOAuth, make$103);
|
|
29475
29574
|
Layer.succeed(McpOAuth, {
|
|
29476
29575
|
statusFor: () => Effect.succeed(Option.none()),
|
|
29477
29576
|
begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
|
|
@@ -29489,7 +29588,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
|
|
|
29489
29588
|
const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
|
|
29490
29589
|
var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
|
|
29491
29590
|
const slotsOf = (registration) => registration.secrets ?? [];
|
|
29492
|
-
const make$
|
|
29591
|
+
const make$102 = Effect.gen(function* () {
|
|
29493
29592
|
const config = yield* ServerConfig$1;
|
|
29494
29593
|
const secrets = yield* ServerSecretStore;
|
|
29495
29594
|
const oauth = yield* McpOAuth;
|
|
@@ -29663,7 +29762,7 @@ const make$101 = Effect.gen(function* () {
|
|
|
29663
29762
|
resolveForSessionAtClaudeUserConfigPath
|
|
29664
29763
|
};
|
|
29665
29764
|
});
|
|
29666
|
-
const layer$
|
|
29765
|
+
const layer$87 = Layer.effect(McpRegistry, make$102);
|
|
29667
29766
|
//#endregion
|
|
29668
29767
|
//#region src/sync/skillDirectory.ts
|
|
29669
29768
|
/**
|
|
@@ -30042,7 +30141,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
|
|
|
30042
30141
|
shareMode: input.shareMode
|
|
30043
30142
|
});
|
|
30044
30143
|
const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
|
|
30045
|
-
const make$
|
|
30144
|
+
const make$101 = Effect.fn("HubLink.make")(function* (environment) {
|
|
30046
30145
|
const secrets = yield* ServerSecretStore;
|
|
30047
30146
|
const env = environment ?? process.env;
|
|
30048
30147
|
const fromEnv = fromEnvironment(env);
|
|
@@ -30115,7 +30214,7 @@ const make$100 = Effect.fn("HubLink.make")(function* (environment) {
|
|
|
30115
30214
|
})
|
|
30116
30215
|
};
|
|
30117
30216
|
});
|
|
30118
|
-
const layer$
|
|
30217
|
+
const layer$86 = Layer.effect(HubLink, make$101());
|
|
30119
30218
|
//#endregion
|
|
30120
30219
|
//#region src/sync/HubAssetClient.ts
|
|
30121
30220
|
/**
|
|
@@ -30148,7 +30247,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
|
|
|
30148
30247
|
const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
|
|
30149
30248
|
const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
|
|
30150
30249
|
var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
|
|
30151
|
-
const make$
|
|
30250
|
+
const make$100 = Effect.gen(function* () {
|
|
30152
30251
|
const http = yield* HttpClient.HttpClient;
|
|
30153
30252
|
const link = yield* HubLink;
|
|
30154
30253
|
const requireSettings = Effect.gen(function* () {
|
|
@@ -30230,7 +30329,7 @@ const make$99 = Effect.gen(function* () {
|
|
|
30230
30329
|
remove
|
|
30231
30330
|
};
|
|
30232
30331
|
});
|
|
30233
|
-
const layer$
|
|
30332
|
+
const layer$85 = Layer.effect(HubAssetClient, make$100);
|
|
30234
30333
|
//#endregion
|
|
30235
30334
|
//#region src/sync/mcpRegistrationFiles.ts
|
|
30236
30335
|
/**
|
|
@@ -31146,7 +31245,7 @@ const EMPTY_REPORT = {
|
|
|
31146
31245
|
unavailable: null
|
|
31147
31246
|
};
|
|
31148
31247
|
var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
|
|
31149
|
-
const make$
|
|
31248
|
+
const make$99 = Effect.gen(function* () {
|
|
31150
31249
|
const client = yield* HubAssetClient;
|
|
31151
31250
|
const link = yield* HubLink;
|
|
31152
31251
|
const settingsStore = yield* ServerSettingsService;
|
|
@@ -31992,7 +32091,7 @@ const make$98 = Effect.gen(function* () {
|
|
|
31992
32091
|
removeLocal
|
|
31993
32092
|
};
|
|
31994
32093
|
});
|
|
31995
|
-
const layer$
|
|
32094
|
+
const layer$84 = Layer.effect(AssetSync, make$99);
|
|
31996
32095
|
//#endregion
|
|
31997
32096
|
//#region src/provider/CompressPrompts.ts
|
|
31998
32097
|
/**
|
|
@@ -32345,7 +32444,7 @@ const findAgentPreset = (requested) => {
|
|
|
32345
32444
|
};
|
|
32346
32445
|
//#endregion
|
|
32347
32446
|
//#region src/cli/assets.ts
|
|
32348
|
-
const SyncServicesLive = layer$
|
|
32447
|
+
const SyncServicesLive = layer$84.pipe(Layer.provideMerge(layer$85), Layer.provideMerge(layer$86), Layer.provideMerge(layer$90.pipe(Layer.provide(layer$115))), Layer.provideMerge(layer$115), Layer.provideMerge(FetchHttpClient.layer));
|
|
32349
32448
|
const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
32350
32449
|
const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
|
|
32351
32450
|
return yield* Effect.gen(function* () {
|
|
@@ -32353,7 +32452,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
|
|
|
32353
32452
|
sync: yield* AssetSync,
|
|
32354
32453
|
link: yield* HubLink
|
|
32355
32454
|
});
|
|
32356
|
-
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$
|
|
32455
|
+
}).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$118(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
|
|
32357
32456
|
});
|
|
32358
32457
|
const STATE_LABEL = {
|
|
32359
32458
|
synced: "synced",
|
|
@@ -33381,7 +33480,7 @@ const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
|
33381
33480
|
"interrupted"
|
|
33382
33481
|
]);
|
|
33383
33482
|
var ThreadBackgroundLivenessService = class extends Context.Service()("@p4code/cli/orchestration/ThreadBackgroundLiveness/ThreadBackgroundLivenessService") {};
|
|
33384
|
-
function make$
|
|
33483
|
+
function make$98() {
|
|
33385
33484
|
const stateByThreadId = /* @__PURE__ */ new Map();
|
|
33386
33485
|
const stateFor = (threadId) => {
|
|
33387
33486
|
const existing = stateByThreadId.get(threadId);
|
|
@@ -33437,7 +33536,7 @@ function make$97() {
|
|
|
33437
33536
|
}
|
|
33438
33537
|
};
|
|
33439
33538
|
}
|
|
33440
|
-
const layer$
|
|
33539
|
+
const layer$83 = Layer.effect(ThreadBackgroundLivenessService, Effect.sync(make$98));
|
|
33441
33540
|
//#endregion
|
|
33442
33541
|
//#region ../../packages/shared/src/sourceControl.ts
|
|
33443
33542
|
const GITHUB_CHANGE_REQUEST_PRESENTATION = {
|
|
@@ -33811,6 +33910,55 @@ function completionAfterEvent(thread, event) {
|
|
|
33811
33910
|
}
|
|
33812
33911
|
}
|
|
33813
33912
|
//#endregion
|
|
33913
|
+
//#region src/orchestration/fusionReviewPolicy.ts
|
|
33914
|
+
function fusionBudgetAction(pair, threadId, text) {
|
|
33915
|
+
if (threadId === pair.watcherThreadId && (text.startsWith("[fusion-review]") || text.startsWith("[fusion-gate]"))) return "review";
|
|
33916
|
+
if (threadId === pair.implementerThreadId && text.startsWith("[fusion-advice]")) return "correction";
|
|
33917
|
+
if ([
|
|
33918
|
+
"[fusion-activation]",
|
|
33919
|
+
"[fusion-advice]",
|
|
33920
|
+
"[fusion-gate]",
|
|
33921
|
+
"[fusion-review]"
|
|
33922
|
+
].some((prefix) => text.startsWith(prefix))) return "protocol";
|
|
33923
|
+
return "human";
|
|
33924
|
+
}
|
|
33925
|
+
function advanceFusionBudget(pair, threadId, text, sequence, commandId = "client") {
|
|
33926
|
+
if (!pair.reviewExperiment || pair.detachedAt !== null || sequence <= (pair.reviewExperiment.lastMessageSequence ?? 0)) return pair.reviewExperiment;
|
|
33927
|
+
const experiment = {
|
|
33928
|
+
...pair.reviewExperiment,
|
|
33929
|
+
lastMessageSequence: sequence
|
|
33930
|
+
};
|
|
33931
|
+
switch (fusionBudgetAction(pair, threadId, text)) {
|
|
33932
|
+
case "review": return {
|
|
33933
|
+
...experiment,
|
|
33934
|
+
automaticReviews: experiment.automaticReviews + 1
|
|
33935
|
+
};
|
|
33936
|
+
case "correction": return experiment.automaticReviews === 0 ? experiment : {
|
|
33937
|
+
...experiment,
|
|
33938
|
+
correctionRounds: experiment.correctionRounds + 1
|
|
33939
|
+
};
|
|
33940
|
+
case "human":
|
|
33941
|
+
if (commandId === null || [
|
|
33942
|
+
"server:",
|
|
33943
|
+
"provider:",
|
|
33944
|
+
"scheduled-task:"
|
|
33945
|
+
].some((prefix) => commandId.startsWith(prefix))) return experiment;
|
|
33946
|
+
return {
|
|
33947
|
+
...experiment,
|
|
33948
|
+
automaticReviews: 0,
|
|
33949
|
+
correctionRounds: 0
|
|
33950
|
+
};
|
|
33951
|
+
case "protocol": return experiment;
|
|
33952
|
+
}
|
|
33953
|
+
}
|
|
33954
|
+
function fusionBudgetBlock(pair, threadId, text) {
|
|
33955
|
+
const experiment = pair.reviewExperiment;
|
|
33956
|
+
if (!experiment || pair.detachedAt !== null) return void 0;
|
|
33957
|
+
const action = fusionBudgetAction(pair, threadId, text);
|
|
33958
|
+
if (action === "review" && experiment.automaticReviews >= experiment.policy.maxAutomaticReviews) return `Automatic review limit (${experiment.policy.maxAutomaticReviews}) reached. Work remains unapproved; send a new instruction to either thread to resume.`;
|
|
33959
|
+
if (action === "correction" && experiment.automaticReviews > 0 && (experiment.correctionRounds >= experiment.policy.maxCorrectionRounds || experiment.automaticReviews >= experiment.policy.maxAutomaticReviews)) return "Correction budget exhausted or no review remains for another correction. Work remains unapproved; send a new instruction to either thread to resume.";
|
|
33960
|
+
}
|
|
33961
|
+
//#endregion
|
|
33814
33962
|
//#region src/attachmentPaths.ts
|
|
33815
33963
|
function normalizeAttachmentRelativePath(rawRelativePath) {
|
|
33816
33964
|
const normalized = NodePath.normalize(rawRelativePath).replace(/^[/\\]+/, "");
|
|
@@ -34243,6 +34391,11 @@ function projectEvent(model, event) {
|
|
|
34243
34391
|
watcherThreadId: payload.watcherThreadId,
|
|
34244
34392
|
lastReviewedImplementerSequence: payload.lastReviewedImplementerSequence,
|
|
34245
34393
|
activationTurnId: payload.activationTurnId ?? null,
|
|
34394
|
+
...payload.reviewPolicy ? { reviewExperiment: {
|
|
34395
|
+
policy: payload.reviewPolicy,
|
|
34396
|
+
automaticReviews: 0,
|
|
34397
|
+
correctionRounds: 0
|
|
34398
|
+
} } : {},
|
|
34246
34399
|
roundCap: payload.roundCap ?? 2,
|
|
34247
34400
|
gateTimeoutMs: payload.gateTimeoutMs ?? 12e4,
|
|
34248
34401
|
activeGate: null,
|
|
@@ -34514,6 +34667,10 @@ function projectEvent(model, event) {
|
|
|
34514
34667
|
} : entry) : [...thread.messages, message]).slice(-2e3);
|
|
34515
34668
|
return {
|
|
34516
34669
|
...nextBase,
|
|
34670
|
+
threadPairs: payload.role === "user" ? (nextBase.threadPairs ?? []).map((pair) => pair.reviewExperiment && pair.detachedAt === null && (pair.implementerThreadId === payload.threadId || pair.watcherThreadId === payload.threadId) ? {
|
|
34671
|
+
...pair,
|
|
34672
|
+
reviewExperiment: advanceFusionBudget(pair, payload.threadId, payload.text, event.sequence, event.commandId) ?? pair.reviewExperiment
|
|
34673
|
+
} : pair) : nextBase.threadPairs ?? [],
|
|
34517
34674
|
threads: updateThread(nextBase.threads, payload.threadId, {
|
|
34518
34675
|
messages: cappedMessages,
|
|
34519
34676
|
updatedAt: event.occurredAt
|
|
@@ -35110,6 +35267,7 @@ const decideCommand = Effect.fn("decideCommand")(function* ({ command, readModel
|
|
|
35110
35267
|
lastReviewedImplementerSequence: readModel.snapshotSequence,
|
|
35111
35268
|
activationTurnId: implementer.latestTurn?.state === "running" ? implementer.latestTurn.turnId : null,
|
|
35112
35269
|
...command.continuationMessageId !== void 0 ? { continuationMessageId: command.continuationMessageId } : {},
|
|
35270
|
+
...command.reviewPolicy !== void 0 ? { reviewPolicy: command.reviewPolicy } : {},
|
|
35113
35271
|
...command.roundCap !== void 0 ? { roundCap: command.roundCap } : {},
|
|
35114
35272
|
...command.gateTimeoutMs !== void 0 ? { gateTimeoutMs: command.gateTimeoutMs } : {},
|
|
35115
35273
|
createdAt: command.createdAt
|
|
@@ -35898,7 +36056,13 @@ const decideCommand = Effect.fn("decideCommand")(function* ({ command, readModel
|
|
|
35898
36056
|
command,
|
|
35899
36057
|
threadId: command.threadId
|
|
35900
36058
|
});
|
|
35901
|
-
|
|
36059
|
+
const activePair = findActiveThreadPair(readModel, command.threadId);
|
|
36060
|
+
const budgetBlock = activePair && fusionBudgetBlock(activePair, command.threadId, command.message.text);
|
|
36061
|
+
if (budgetBlock) return yield* new OrchestrationCommandInvariantError({
|
|
36062
|
+
commandType: command.type,
|
|
36063
|
+
detail: budgetBlock
|
|
36064
|
+
});
|
|
36065
|
+
if (activePair?.watcherThreadId === command.threadId && targetThread.interactionMode !== "default") return yield* decideCommandSequence({
|
|
35902
36066
|
readModel,
|
|
35903
36067
|
commands: [{
|
|
35904
36068
|
type: "thread.interaction-mode.set",
|
|
@@ -36497,6 +36661,7 @@ function commandToAggregateRef(command) {
|
|
|
36497
36661
|
}
|
|
36498
36662
|
const makeOrchestrationEngine = Effect.gen(function* () {
|
|
36499
36663
|
const sql = yield* SqlClient.SqlClient;
|
|
36664
|
+
const settingsService = yield* Effect.serviceOption(ServerSettingsService);
|
|
36500
36665
|
const eventStore = yield* OrchestrationEventStore;
|
|
36501
36666
|
const commandReceiptRepository = yield* OrchestrationCommandReceiptRepository;
|
|
36502
36667
|
const projectionPipeline = yield* OrchestrationProjectionPipeline;
|
|
@@ -36548,8 +36713,19 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
36548
36713
|
detail: existingReceipt.value.error ?? "Previously rejected."
|
|
36549
36714
|
});
|
|
36550
36715
|
}
|
|
36716
|
+
let command = envelope.command;
|
|
36717
|
+
if (command.type === "thread-pair.create" && command.reviewPolicy === void 0 && Option.isSome(settingsService)) {
|
|
36718
|
+
const settings = yield* settingsService.value.getSettings.pipe(Effect.mapError(() => new OrchestrationCommandInvariantError({
|
|
36719
|
+
commandType: "thread-pair.create",
|
|
36720
|
+
detail: "Could not read the review policy settings."
|
|
36721
|
+
})));
|
|
36722
|
+
command = {
|
|
36723
|
+
...command,
|
|
36724
|
+
reviewPolicy: settings.fusionReviewPolicy
|
|
36725
|
+
};
|
|
36726
|
+
}
|
|
36551
36727
|
const eventBase = yield* decideOrchestrationCommand({
|
|
36552
|
-
command
|
|
36728
|
+
command,
|
|
36553
36729
|
readModel: commandReadModel,
|
|
36554
36730
|
hasLiveBackgroundWork: "threadId" in envelope.command && backgroundLiveness.getThreadBackgroundLiveness(envelope.command.threadId) !== null
|
|
36555
36731
|
}).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.mapError((cause) => isOrchestrationCommandInvariantError(cause) ? cause : new OrchestrationCommandInvariantError({
|
|
@@ -36653,7 +36829,7 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
36653
36829
|
latestSequence: Effect.sync(() => commandReadModel.snapshotSequence)
|
|
36654
36830
|
};
|
|
36655
36831
|
});
|
|
36656
|
-
const OrchestrationEngineLive = Layer.effect(OrchestrationEngineService, makeOrchestrationEngine).pipe(Layer.provide(layer$
|
|
36832
|
+
const OrchestrationEngineLive = Layer.effect(OrchestrationEngineService, makeOrchestrationEngine).pipe(Layer.provide(layer$83));
|
|
36657
36833
|
//#endregion
|
|
36658
36834
|
//#region src/persistence/Services/ProjectionPendingApprovals.ts
|
|
36659
36835
|
/**
|
|
@@ -38132,6 +38308,8 @@ const ProjectionThreadRepositoryLive = Layer.effect(ProjectionThreadRepository,
|
|
|
38132
38308
|
* Counted rather than flagged so a lost completion can only strand one task,
|
|
38133
38309
|
* and read as a boolean by the shell.
|
|
38134
38310
|
*/
|
|
38311
|
+
const decodeReviewExperiment = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(FusionReviewExperiment));
|
|
38312
|
+
const encodeReviewExperiment = Schema$1.encodeEffect(Schema$1.fromJsonString(FusionReviewExperiment));
|
|
38135
38313
|
const ORCHESTRATION_PROJECTOR_NAMES = {
|
|
38136
38314
|
projects: "projection.projects",
|
|
38137
38315
|
threads: "projection.threads",
|
|
@@ -38399,7 +38577,32 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
38399
38577
|
});
|
|
38400
38578
|
const applyThreadPairsProjection = Effect.fn("applyThreadPairsProjection")(function* (event, _attachmentSideEffects) {
|
|
38401
38579
|
switch (event.type) {
|
|
38402
|
-
case "thread-
|
|
38580
|
+
case "thread.message-sent": {
|
|
38581
|
+
if (event.payload.role !== "user") return;
|
|
38582
|
+
const rows = yield* sql`
|
|
38583
|
+
SELECT pair_id AS id, implementer_thread_id AS "implementerThreadId", watcher_thread_id AS "watcherThreadId",
|
|
38584
|
+
review_experiment_json AS "experimentJson", created_at AS "createdAt"
|
|
38585
|
+
FROM thread_pairs WHERE detached_at IS NULL AND review_experiment_json IS NOT NULL
|
|
38586
|
+
AND (implementer_thread_id = ${event.payload.threadId} OR watcher_thread_id = ${event.payload.threadId})`.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.fusionBudget:read")));
|
|
38587
|
+
for (const row of rows) {
|
|
38588
|
+
const experiment = yield* decodeReviewExperiment(row.experimentJson).pipe(Effect.orDie);
|
|
38589
|
+
const next = advanceFusionBudget({
|
|
38590
|
+
...row,
|
|
38591
|
+
reviewExperiment: experiment,
|
|
38592
|
+
detachedAt: null
|
|
38593
|
+
}, event.payload.threadId, event.payload.text, event.sequence, event.commandId);
|
|
38594
|
+
if (!next) continue;
|
|
38595
|
+
const encoded = yield* encodeReviewExperiment(next).pipe(Effect.orDie);
|
|
38596
|
+
yield* sql`UPDATE thread_pairs SET review_experiment_json = ${encoded} WHERE pair_id = ${row.id}`.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.fusionBudget:update")));
|
|
38597
|
+
}
|
|
38598
|
+
return;
|
|
38599
|
+
}
|
|
38600
|
+
case "thread-pair.created": {
|
|
38601
|
+
const experimentJson = event.payload.reviewPolicy ? yield* encodeReviewExperiment({
|
|
38602
|
+
policy: event.payload.reviewPolicy,
|
|
38603
|
+
automaticReviews: 0,
|
|
38604
|
+
correctionRounds: 0
|
|
38605
|
+
}).pipe(Effect.orDie) : null;
|
|
38403
38606
|
yield* sql`
|
|
38404
38607
|
INSERT INTO thread_pairs (
|
|
38405
38608
|
pair_id,
|
|
@@ -38409,6 +38612,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
38409
38612
|
activation_turn_id,
|
|
38410
38613
|
round_cap,
|
|
38411
38614
|
gate_timeout_ms,
|
|
38615
|
+
review_experiment_json,
|
|
38412
38616
|
active_gate_json,
|
|
38413
38617
|
created_at,
|
|
38414
38618
|
detached_at
|
|
@@ -38420,6 +38624,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
38420
38624
|
${event.payload.activationTurnId ?? null},
|
|
38421
38625
|
${event.payload.roundCap ?? 2},
|
|
38422
38626
|
${event.payload.gateTimeoutMs ?? 12e4},
|
|
38627
|
+
${experimentJson},
|
|
38423
38628
|
NULL,
|
|
38424
38629
|
${event.payload.createdAt},
|
|
38425
38630
|
NULL
|
|
@@ -38431,11 +38636,13 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
38431
38636
|
activation_turn_id = excluded.activation_turn_id,
|
|
38432
38637
|
round_cap = excluded.round_cap,
|
|
38433
38638
|
gate_timeout_ms = excluded.gate_timeout_ms,
|
|
38639
|
+
review_experiment_json = excluded.review_experiment_json,
|
|
38434
38640
|
active_gate_json = NULL,
|
|
38435
38641
|
created_at = excluded.created_at,
|
|
38436
38642
|
detached_at = NULL
|
|
38437
38643
|
`.pipe(Effect.mapError(toPersistenceSqlError("ProjectionPipeline.threadPairs:create")));
|
|
38438
38644
|
return;
|
|
38645
|
+
}
|
|
38439
38646
|
case "thread-pair.gate-opened":
|
|
38440
38647
|
case "thread-pair.gate-advanced":
|
|
38441
38648
|
yield* sql`
|
|
@@ -39755,12 +39962,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
|
|
|
39755
39962
|
stderrInvalidUtf8: stderr.invalidUtf8
|
|
39756
39963
|
};
|
|
39757
39964
|
});
|
|
39758
|
-
const make$
|
|
39965
|
+
const make$97 = Effect.fn("ProcessRunner.make")(function* () {
|
|
39759
39966
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
39760
39967
|
const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
|
|
39761
39968
|
return ProcessRunner.of({ run });
|
|
39762
39969
|
});
|
|
39763
|
-
const layer$
|
|
39970
|
+
const layer$82 = Layer.effect(ProcessRunner, make$97());
|
|
39764
39971
|
//#endregion
|
|
39765
39972
|
//#region src/project/RepositoryIdentityResolver.ts
|
|
39766
39973
|
const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
|
|
@@ -39851,7 +40058,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
|
|
|
39851
40058
|
rootPath: cacheKey
|
|
39852
40059
|
}) : null;
|
|
39853
40060
|
});
|
|
39854
|
-
const make$
|
|
40061
|
+
const make$96 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
|
|
39855
40062
|
const processRunner = yield* ProcessRunner;
|
|
39856
40063
|
const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
|
|
39857
40064
|
capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
|
|
@@ -39866,7 +40073,7 @@ const make$95 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
|
|
|
39866
40073
|
});
|
|
39867
40074
|
return RepositoryIdentityResolver.of({ resolve });
|
|
39868
40075
|
});
|
|
39869
|
-
const layer$
|
|
40076
|
+
const layer$81 = Layer.effect(RepositoryIdentityResolver, make$96()).pipe(Layer.provide(layer$82));
|
|
39870
40077
|
//#endregion
|
|
39871
40078
|
//#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
|
|
39872
40079
|
const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
|
|
@@ -39923,6 +40130,7 @@ const ProjectionThreadPairDbRowSchema = Schema$1.Struct({
|
|
|
39923
40130
|
activationTurnId: Schema$1.NullOr(TurnId),
|
|
39924
40131
|
roundCap: NonNegativeInt,
|
|
39925
40132
|
gateTimeoutMs: NonNegativeInt,
|
|
40133
|
+
reviewExperiment: Schema$1.NullOr(Schema$1.fromJsonString(FusionReviewExperiment)),
|
|
39926
40134
|
activeGate: Schema$1.NullOr(Schema$1.fromJsonString(OrchestrationThreadPairGate)),
|
|
39927
40135
|
createdAt: IsoDateTime,
|
|
39928
40136
|
detachedAt: Schema$1.NullOr(IsoDateTime)
|
|
@@ -40175,6 +40383,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
40175
40383
|
activation_turn_id AS "activationTurnId",
|
|
40176
40384
|
round_cap AS "roundCap",
|
|
40177
40385
|
gate_timeout_ms AS "gateTimeoutMs",
|
|
40386
|
+
review_experiment_json AS "reviewExperiment",
|
|
40178
40387
|
active_gate_json AS "activeGate",
|
|
40179
40388
|
created_at AS "createdAt",
|
|
40180
40389
|
detached_at AS "detachedAt"
|
|
@@ -40194,6 +40403,7 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
40194
40403
|
activation_turn_id AS "activationTurnId",
|
|
40195
40404
|
round_cap AS "roundCap",
|
|
40196
40405
|
gate_timeout_ms AS "gateTimeoutMs",
|
|
40406
|
+
review_experiment_json AS "reviewExperiment",
|
|
40197
40407
|
active_gate_json AS "activeGate",
|
|
40198
40408
|
created_at AS "createdAt",
|
|
40199
40409
|
detached_at AS "detachedAt"
|
|
@@ -41541,6 +41751,72 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
41541
41751
|
if (isPersistenceError(error)) return error;
|
|
41542
41752
|
return toPersistenceSqlError("ProjectionSnapshotQuery.getSnapshot:query")(error);
|
|
41543
41753
|
}));
|
|
41754
|
+
const readHandoffThread = SqlSchema.findOneOption({
|
|
41755
|
+
Request: ThreadIdLookupInput,
|
|
41756
|
+
Result: ProjectionBtwThreadRowSchema,
|
|
41757
|
+
execute: ({ threadId }) => sql`
|
|
41758
|
+
SELECT threads.project_id AS "projectId",
|
|
41759
|
+
COALESCE(projects.workspace_root, threads.worktree_path, '') AS cwd
|
|
41760
|
+
FROM projection_threads AS threads
|
|
41761
|
+
LEFT JOIN projection_projects AS projects ON projects.project_id = threads.project_id
|
|
41762
|
+
WHERE threads.thread_id = ${threadId} AND threads.deleted_at IS NULL
|
|
41763
|
+
AND (threads.project_id = ${P4_CHAT_PROJECT_ID} OR projects.deleted_at IS NULL)
|
|
41764
|
+
`
|
|
41765
|
+
});
|
|
41766
|
+
const readHandoffRows = SqlSchema.findAll({
|
|
41767
|
+
Request: ThreadIdLookupInput,
|
|
41768
|
+
Result: Schema$1.Struct({
|
|
41769
|
+
threadId: ThreadId,
|
|
41770
|
+
role: Schema$1.String,
|
|
41771
|
+
text: Schema$1.String
|
|
41772
|
+
}),
|
|
41773
|
+
execute: ({ threadId }) => sql`
|
|
41774
|
+
WITH latest_pair AS (
|
|
41775
|
+
SELECT implementer_thread_id, watcher_thread_id FROM thread_pairs
|
|
41776
|
+
WHERE implementer_thread_id = ${threadId} OR watcher_thread_id = ${threadId}
|
|
41777
|
+
ORDER BY created_at DESC LIMIT 1
|
|
41778
|
+
), sources AS (
|
|
41779
|
+
SELECT ${threadId} AS id
|
|
41780
|
+
UNION SELECT implementer_thread_id FROM latest_pair
|
|
41781
|
+
UNION SELECT watcher_thread_id FROM latest_pair
|
|
41782
|
+
), ranked AS (
|
|
41783
|
+
SELECT messages.thread_id AS "threadId", messages.role,
|
|
41784
|
+
substr(messages.text, -${BTW_CONTEXT_CHARACTER_LIMIT}) AS text,
|
|
41785
|
+
messages.created_at, messages.message_id,
|
|
41786
|
+
ROW_NUMBER() OVER (PARTITION BY messages.thread_id ORDER BY messages.created_at DESC, messages.message_id DESC) AS recent,
|
|
41787
|
+
ROW_NUMBER() OVER (PARTITION BY messages.thread_id ORDER BY messages.created_at, messages.message_id) AS earliest
|
|
41788
|
+
FROM projection_thread_messages AS messages
|
|
41789
|
+
JOIN projection_threads AS threads ON threads.thread_id = messages.thread_id
|
|
41790
|
+
WHERE messages.thread_id IN (SELECT id FROM sources)
|
|
41791
|
+
AND threads.deleted_at IS NULL AND messages.is_streaming = 0
|
|
41792
|
+
AND messages.role IN ('user', 'assistant')
|
|
41793
|
+
) SELECT "threadId", role, text FROM ranked
|
|
41794
|
+
WHERE recent <= ${BTW_CONTEXT_MESSAGE_LIMIT} OR earliest = 1
|
|
41795
|
+
ORDER BY created_at, message_id
|
|
41796
|
+
`
|
|
41797
|
+
});
|
|
41798
|
+
const getHandoffContext = Effect.fn("ProjectionSnapshotQuery.getHandoffContext")(function* (threadId) {
|
|
41799
|
+
return yield* sql.withTransaction(Effect.gen(function* () {
|
|
41800
|
+
const thread = yield* readHandoffThread({ threadId });
|
|
41801
|
+
if (Option.isNone(thread)) return Option.none();
|
|
41802
|
+
const rows = yield* readHandoffRows({ threadId });
|
|
41803
|
+
const sourceIds = [...new Set(rows.map((row) => row.threadId))];
|
|
41804
|
+
const sourceCount = Math.max(1, sourceIds.length);
|
|
41805
|
+
const budget = Math.floor((BTW_CONTEXT_CHARACTER_LIMIT - 2 * (sourceCount - 1)) / sourceCount);
|
|
41806
|
+
const transcript = sourceIds.map((sourceId) => {
|
|
41807
|
+
const text = rows.filter((row) => row.threadId === sourceId).map((row) => `${row.role}: ${row.text}`).join("\n\n");
|
|
41808
|
+
const heading = `Thread ${sourceId} (bounded history):\n`;
|
|
41809
|
+
const available = budget - heading.length;
|
|
41810
|
+
const omission = "\n[Earlier history omitted]\n";
|
|
41811
|
+
const beginning = Math.floor(available / 4);
|
|
41812
|
+
return heading + (text.length <= available ? text : text.slice(0, beginning) + omission + text.slice(-(available - beginning - 27)));
|
|
41813
|
+
}).join("\n\n");
|
|
41814
|
+
return Option.some({
|
|
41815
|
+
...thread.value,
|
|
41816
|
+
transcript
|
|
41817
|
+
});
|
|
41818
|
+
})).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getHandoffContext:query", "ProjectionSnapshotQuery.getHandoffContext:decodeRows")));
|
|
41819
|
+
});
|
|
41544
41820
|
const getBtwContext = Effect.fn("ProjectionSnapshotQuery.getBtwContext")(function* (threadId) {
|
|
41545
41821
|
const [thread, rows] = yield* Effect.all([getBtwThreadRow({ threadId }), listBtwContextRows({ threadId })]).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$1("ProjectionSnapshotQuery.getBtwContext:query", "ProjectionSnapshotQuery.getBtwContext:decodeRows")));
|
|
41546
41822
|
if (Option.isNone(thread)) return Option.none();
|
|
@@ -42124,11 +42400,12 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
42124
42400
|
getThreadPairById,
|
|
42125
42401
|
getThreadShellById,
|
|
42126
42402
|
getThreadDetailById,
|
|
42403
|
+
getHandoffContext,
|
|
42127
42404
|
getBtwContext,
|
|
42128
42405
|
getThreadDetailSnapshot
|
|
42129
42406
|
};
|
|
42130
42407
|
});
|
|
42131
|
-
const OrchestrationProjectionSnapshotQueryLive = Layer.effect(ProjectionSnapshotQuery, makeProjectionSnapshotQuery).pipe(Layer.provide(layer$
|
|
42408
|
+
const OrchestrationProjectionSnapshotQueryLive = Layer.effect(ProjectionSnapshotQuery, makeProjectionSnapshotQuery).pipe(Layer.provide(layer$83));
|
|
42132
42409
|
//#endregion
|
|
42133
42410
|
//#region src/orchestration/Services/ThreadEventStream.ts
|
|
42134
42411
|
var ThreadEventStreamService = class extends Context.Service()("@p4code/cli/orchestration/Services/ThreadEventStream/ThreadEventStreamService") {};
|
|
@@ -42398,7 +42675,7 @@ const OrchestrationProjectionPipelineLayerLive = OrchestrationProjectionPipeline
|
|
|
42398
42675
|
* ingestion writes it, and layers memoize by reference, so both must receive
|
|
42399
42676
|
* THIS layer or they would each get their own empty registry.
|
|
42400
42677
|
*/
|
|
42401
|
-
const ThreadBackgroundLivenessLayerLive = layer$
|
|
42678
|
+
const ThreadBackgroundLivenessLayerLive = layer$83;
|
|
42402
42679
|
const OrchestrationInfrastructureLayerLive = Layer.mergeAll(OrchestrationProjectionSnapshotQueryLive, OrchestrationEventInfrastructureLayerLive, OrchestrationProjectionPipelineLayerLive, ThreadBackgroundLivenessLayerLive);
|
|
42403
42680
|
const OrchestrationEngineLayerLive = OrchestrationEngineLive.pipe(Layer.provide(OrchestrationInfrastructureLayerLive));
|
|
42404
42681
|
const OrchestrationLayerLive = Layer.mergeAll(OrchestrationInfrastructureLayerLive, OrchestrationEngineLayerLive, ThreadEventStreamLive.pipe(Layer.provide(OrchestrationEngineLayerLive), Layer.provide(OrchestrationEventStoreLive)));
|
|
@@ -42873,7 +43150,7 @@ function mergeWithDefaultKeybindings(custom) {
|
|
|
42873
43150
|
* Keybindings - Service tag for keybinding configuration operations.
|
|
42874
43151
|
*/
|
|
42875
43152
|
var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
|
|
42876
|
-
const make$
|
|
43153
|
+
const make$95 = Effect.gen(function* () {
|
|
42877
43154
|
const { keybindingsConfigPath } = yield* ServerConfig$1;
|
|
42878
43155
|
const fs = yield* FileSystem.FileSystem;
|
|
42879
43156
|
const path = yield* Path$1.Path;
|
|
@@ -43134,7 +43411,7 @@ const make$94 = Effect.gen(function* () {
|
|
|
43134
43411
|
}))
|
|
43135
43412
|
};
|
|
43136
43413
|
});
|
|
43137
|
-
const layer$
|
|
43414
|
+
const layer$80 = Layer.effect(Keybindings, make$95);
|
|
43138
43415
|
//#endregion
|
|
43139
43416
|
//#region src/process/externalLauncher.ts
|
|
43140
43417
|
/**
|
|
@@ -43361,7 +43638,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
|
|
|
43361
43638
|
cause
|
|
43362
43639
|
}));
|
|
43363
43640
|
});
|
|
43364
|
-
const make$
|
|
43641
|
+
const make$94 = Effect.gen(function* () {
|
|
43365
43642
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
43366
43643
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
43367
43644
|
const path = yield* Path$1.Path;
|
|
@@ -43372,7 +43649,7 @@ const make$93 = Effect.gen(function* () {
|
|
|
43372
43649
|
launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
|
|
43373
43650
|
});
|
|
43374
43651
|
});
|
|
43375
|
-
const layer$
|
|
43652
|
+
const layer$79 = Layer.effect(ExternalLauncher, make$94);
|
|
43376
43653
|
//#endregion
|
|
43377
43654
|
//#region src/orchestration/Services/OrchestrationReactor.ts
|
|
43378
43655
|
/**
|
|
@@ -43390,7 +43667,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
|
|
|
43390
43667
|
//#endregion
|
|
43391
43668
|
//#region src/serverLifecycleEvents.ts
|
|
43392
43669
|
var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
|
|
43393
|
-
const make$
|
|
43670
|
+
const make$93 = Effect.gen(function* () {
|
|
43394
43671
|
const pubsub = yield* PubSub.unbounded();
|
|
43395
43672
|
const state = yield* Ref.make({
|
|
43396
43673
|
sequence: 0,
|
|
@@ -43414,7 +43691,7 @@ const make$92 = Effect.gen(function* () {
|
|
|
43414
43691
|
}
|
|
43415
43692
|
};
|
|
43416
43693
|
});
|
|
43417
|
-
const layer$
|
|
43694
|
+
const layer$78 = Layer.effect(ServerLifecycleEvents, make$93);
|
|
43418
43695
|
//#endregion
|
|
43419
43696
|
//#region src/telemetry/Identify.ts
|
|
43420
43697
|
const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
|
|
@@ -43587,7 +43864,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
|
|
|
43587
43864
|
/** No-op layer for callers that intentionally disable telemetry. */
|
|
43588
43865
|
static layerTest = Layer.succeed(AnalyticsService, inert);
|
|
43589
43866
|
};
|
|
43590
|
-
const make$
|
|
43867
|
+
const make$92 = Effect.gen(function* () {
|
|
43591
43868
|
const telemetryConfig = yield* TelemetryEnvConfig;
|
|
43592
43869
|
const posthogKey = telemetryConfig.posthogKey.trim();
|
|
43593
43870
|
if (!telemetryConfig.enabled || posthogKey === "") return inert;
|
|
@@ -43657,7 +43934,7 @@ const make$91 = Effect.gen(function* () {
|
|
|
43657
43934
|
flush
|
|
43658
43935
|
});
|
|
43659
43936
|
});
|
|
43660
|
-
const layer$
|
|
43937
|
+
const layer$77 = Layer.effect(AnalyticsService, make$92);
|
|
43661
43938
|
AnalyticsService.layerTest;
|
|
43662
43939
|
//#endregion
|
|
43663
43940
|
//#region src/provider/Services/ProviderSessionDirectory.ts
|
|
@@ -44088,7 +44365,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
|
|
|
44088
44365
|
}
|
|
44089
44366
|
};
|
|
44090
44367
|
var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
|
|
44091
|
-
const make$
|
|
44368
|
+
const make$91 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
44092
44369
|
const hostExecPath = yield* HostProcessExecutablePath;
|
|
44093
44370
|
const hostArguments = yield* HostProcessArguments;
|
|
44094
44371
|
const host = input.host ?? {
|
|
@@ -44310,7 +44587,7 @@ const make$90 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
|
44310
44587
|
logPath
|
|
44311
44588
|
});
|
|
44312
44589
|
});
|
|
44313
|
-
const layer$
|
|
44590
|
+
const layer$76 = (input) => Layer.effect(BootService, make$91(input));
|
|
44314
44591
|
//#endregion
|
|
44315
44592
|
//#region src/service/selfUpdate.ts
|
|
44316
44593
|
/**
|
|
@@ -44385,7 +44662,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
|
|
|
44385
44662
|
return null;
|
|
44386
44663
|
});
|
|
44387
44664
|
var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
|
|
44388
|
-
const make$
|
|
44665
|
+
const make$90 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
44389
44666
|
const serverConfig = yield* ServerConfig$1;
|
|
44390
44667
|
const settings = yield* ServerSettingsService;
|
|
44391
44668
|
const continuationContext = yield* Effect.context();
|
|
@@ -44548,7 +44825,7 @@ const make$89 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
|
44548
44825
|
});
|
|
44549
44826
|
return ServerSelfUpdate.of({ update });
|
|
44550
44827
|
});
|
|
44551
|
-
const layer$
|
|
44828
|
+
const layer$75 = Layer.effect(ServerSelfUpdate, make$90()).pipe(Layer.provide(layer$82));
|
|
44552
44829
|
//#endregion
|
|
44553
44830
|
//#region src/environment/ServerEnvironmentLabel.ts
|
|
44554
44831
|
const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
|
|
@@ -44680,7 +44957,7 @@ function platformArch(architecture) {
|
|
|
44680
44957
|
default: return "other";
|
|
44681
44958
|
}
|
|
44682
44959
|
}
|
|
44683
|
-
const make$
|
|
44960
|
+
const make$89 = Effect.gen(function* () {
|
|
44684
44961
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
44685
44962
|
const path = yield* Path$1.Path;
|
|
44686
44963
|
const serverConfig = yield* ServerConfig$1;
|
|
@@ -44758,7 +45035,7 @@ const make$88 = Effect.gen(function* () {
|
|
|
44758
45035
|
* state. It intentionally has no fallback Layer.succeed value: callers must
|
|
44759
45036
|
* provide the external platform services and a ServerConfig.
|
|
44760
45037
|
*/
|
|
44761
|
-
const layer$
|
|
45038
|
+
const layer$74 = Layer.effect(ServerEnvironment, make$89).pipe(Layer.provide(layer$82));
|
|
44762
45039
|
//#endregion
|
|
44763
45040
|
//#region src/provider/Services/ProviderSessionReaper.ts
|
|
44764
45041
|
var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
|
|
@@ -45113,7 +45390,7 @@ function daemonPortLine(line) {
|
|
|
45113
45390
|
const port = Number(raw);
|
|
45114
45391
|
return Number.isInteger(port) && port > 0 && port <= MAX_PORT$1 ? port : null;
|
|
45115
45392
|
}
|
|
45116
|
-
const make$
|
|
45393
|
+
const make$88 = Effect.fn("AgentDeviceProcess.make")(function* () {
|
|
45117
45394
|
const fs = yield* FileSystem.FileSystem;
|
|
45118
45395
|
const path = yield* Path$1.Path;
|
|
45119
45396
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
@@ -45225,14 +45502,14 @@ const make$87 = Effect.fn("AgentDeviceProcess.make")(function* () {
|
|
|
45225
45502
|
});
|
|
45226
45503
|
return { start };
|
|
45227
45504
|
});
|
|
45228
|
-
const layer$
|
|
45505
|
+
const layer$73 = Layer.effect(AgentDeviceProcess, make$88());
|
|
45229
45506
|
//#endregion
|
|
45230
45507
|
//#region src/device/DeviceDiscovery.ts
|
|
45231
45508
|
var DeviceDiscoveryFailure = class extends Data.TaggedError("DeviceDiscoveryFailure") {};
|
|
45232
45509
|
const MAX_DEVICES = 512;
|
|
45233
45510
|
const MAX_RESPONSE_BYTES$6 = 1024 * 1024;
|
|
45234
45511
|
const MAX_DEVICE_LABEL = 512;
|
|
45235
|
-
const REQUEST_TIMEOUT_MS$
|
|
45512
|
+
const REQUEST_TIMEOUT_MS$6 = 15e3;
|
|
45236
45513
|
const HubDevice = Schema$1.Struct({
|
|
45237
45514
|
id: DeviceId,
|
|
45238
45515
|
name: Schema$1.String.check(Schema$1.isMinLength(1), Schema$1.isMaxLength(MAX_DEVICE_LABEL)),
|
|
@@ -45258,7 +45535,7 @@ const decodeDeviceDiscovery = (hostId, body) => Schema$1.decodeUnknownEffect(Sch
|
|
|
45258
45535
|
partial: (value.errors?.length ?? 0) > 0
|
|
45259
45536
|
});
|
|
45260
45537
|
}));
|
|
45261
|
-
const make$
|
|
45538
|
+
const make$87 = Effect.fn("DeviceDiscovery.make")(function* () {
|
|
45262
45539
|
const http = yield* HttpClient.HttpClient;
|
|
45263
45540
|
return Effect.fn("DeviceDiscovery.read")(function* (input) {
|
|
45264
45541
|
const origin = yield* Effect.try(() => new URL(input.ready.hub.origin));
|
|
@@ -45275,7 +45552,10 @@ const make$86 = Effect.fn("DeviceDiscovery.make")(function* () {
|
|
|
45275
45552
|
});
|
|
45276
45553
|
if (body.invalidUtf8 || body.truncated) return yield* new DeviceDiscoveryFailure({ message: "Invalid device discovery response." });
|
|
45277
45554
|
const result = yield* decodeDeviceDiscovery(input.hostId, body.text);
|
|
45278
|
-
const
|
|
45555
|
+
const adapterDevices = input.ready.xcode ? yield* input.ready.xcode.discover : [];
|
|
45556
|
+
const simulatorIds = new Set(adapterDevices.map((device) => device.id));
|
|
45557
|
+
const devices = [...result.devices.filter((device) => device.platform !== "ios" || device.physical || !simulatorIds.has(device.id)), ...adapterDevices];
|
|
45558
|
+
if (devices.length > MAX_DEVICES || new Set(devices.map((device) => device.id)).size !== devices.length || adapterDevices.some((device) => device.hostId !== input.hostId || device.platform !== "ios" || device.physical)) return yield* new DeviceDiscoveryFailure({ message: "Invalid Xcode simulator identity." });
|
|
45279
45559
|
if (input.androidAvailable) {
|
|
45280
45560
|
const avds = yield* input.ready.run("emulator", ["-list-avds"]);
|
|
45281
45561
|
if (avds.code !== 0) return yield* new DeviceDiscoveryFailure({ message: "Android virtual device discovery failed." });
|
|
@@ -45299,7 +45579,7 @@ const make$86 = Effect.fn("DeviceDiscovery.make")(function* () {
|
|
|
45299
45579
|
devices,
|
|
45300
45580
|
partial: result.partial
|
|
45301
45581
|
};
|
|
45302
|
-
}, Effect.scoped, Effect.timeout(Duration.millis(REQUEST_TIMEOUT_MS$
|
|
45582
|
+
}, Effect.scoped, Effect.timeout(Duration.millis(REQUEST_TIMEOUT_MS$6)), Effect.mapError(() => new DeviceOperationError({
|
|
45303
45583
|
operation: "list",
|
|
45304
45584
|
reason: "request_failed",
|
|
45305
45585
|
cause: "Device discovery unavailable."
|
|
@@ -45317,7 +45597,7 @@ const Result = Schema$1.Struct({
|
|
|
45317
45597
|
serial: Schema$1.optional(DeviceId),
|
|
45318
45598
|
error: Schema$1.optional(Schema$1.String)
|
|
45319
45599
|
});
|
|
45320
|
-
const make$
|
|
45600
|
+
const make$86 = Effect.fn("DeviceHubActions.make")(function* () {
|
|
45321
45601
|
const http = yield* HttpClient.HttpClient;
|
|
45322
45602
|
const post = Effect.fn("DeviceHubActions.post")(function* (ready, route, payload, timeoutMs) {
|
|
45323
45603
|
return yield* Effect.gen(function* () {
|
|
@@ -45386,7 +45666,7 @@ function sessionsToClose(sessions, input) {
|
|
|
45386
45666
|
//#endregion
|
|
45387
45667
|
//#region src/device/DeviceCommandLeases.ts
|
|
45388
45668
|
/** Owns commands by exact session object, so close/reopen cannot revive an old lease. */
|
|
45389
|
-
const make$
|
|
45669
|
+
const make$85 = Effect.fn("DeviceCommandLeases.make")(function* () {
|
|
45390
45670
|
const lock = yield* Semaphore.make(1);
|
|
45391
45671
|
const entries = /* @__PURE__ */ new Map();
|
|
45392
45672
|
const revoked = /* @__PURE__ */ new WeakSet();
|
|
@@ -45432,7 +45712,7 @@ const make$84 = Effect.fn("DeviceCommandLeases.make")(function* () {
|
|
|
45432
45712
|
//#endregion
|
|
45433
45713
|
//#region src/device/DeviceThreadLeases.ts
|
|
45434
45714
|
/** Thread retirement also cancels opens that have not created a session yet. */
|
|
45435
|
-
const make$
|
|
45715
|
+
const make$84 = Effect.fn("DeviceThreadLeases.make")(function* () {
|
|
45436
45716
|
const lock = yield* Semaphore.make(1);
|
|
45437
45717
|
const scopes = /* @__PURE__ */ new Map();
|
|
45438
45718
|
const blocked = /* @__PURE__ */ new Set();
|
|
@@ -45480,7 +45760,7 @@ const make$83 = Effect.fn("DeviceThreadLeases.make")(function* () {
|
|
|
45480
45760
|
//#region src/device/DeviceHostRegistry.ts
|
|
45481
45761
|
const sameConfig = (a, b) => a === b || a !== null && b !== null && a.id === b.id && a.label === b.label && a.target === b.target && a.port === b.port && a.identityFile === b.identityFile;
|
|
45482
45762
|
/** Owns configuration generations; use() interrupts in-flight work before a host is retired. */
|
|
45483
|
-
const make$
|
|
45763
|
+
const make$83 = Effect.fn("DeviceHostRegistry.make")(function* (factories) {
|
|
45484
45764
|
const factoryContext = yield* Effect.context();
|
|
45485
45765
|
const lock = yield* Semaphore.make(1);
|
|
45486
45766
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -45603,6 +45883,675 @@ const start = Effect.fn("DeviceHostSettings.start")(function* (input) {
|
|
|
45603
45883
|
return { refresh };
|
|
45604
45884
|
});
|
|
45605
45885
|
//#endregion
|
|
45886
|
+
//#region src/device/DeviceScreenshot.ts
|
|
45887
|
+
const MAX_SCREENSHOT_BYTES = 8 * 1024 * 1024;
|
|
45888
|
+
var DeviceScreenshotFailure = class extends Data.TaggedError("DeviceScreenshotFailure") {};
|
|
45889
|
+
const MAX_DIMENSION = 16384;
|
|
45890
|
+
const MAX_PIXELS = 64 * 1024 * 1024;
|
|
45891
|
+
const SCREENSHOT_TIMEOUT_MS = 2e4;
|
|
45892
|
+
const PNG_HEADER_BYTES = 33;
|
|
45893
|
+
const PNG_CHUNK_OVERHEAD = 12;
|
|
45894
|
+
const PNG_SIGNATURE = Buffer.from([
|
|
45895
|
+
137,
|
|
45896
|
+
80,
|
|
45897
|
+
78,
|
|
45898
|
+
71,
|
|
45899
|
+
13,
|
|
45900
|
+
10,
|
|
45901
|
+
26,
|
|
45902
|
+
10
|
|
45903
|
+
]);
|
|
45904
|
+
function pngDimensions(png) {
|
|
45905
|
+
const buffer = Buffer.from(png.buffer, png.byteOffset, png.byteLength);
|
|
45906
|
+
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." });
|
|
45907
|
+
const width = buffer.readUInt32BE(16);
|
|
45908
|
+
const height = buffer.readUInt32BE(20);
|
|
45909
|
+
if (!width || !height || width > MAX_DIMENSION || height > MAX_DIMENSION || width * height > MAX_PIXELS) throw new DeviceScreenshotFailure({ message: "Screenshot dimensions exceed limits." });
|
|
45910
|
+
let offset = PNG_HEADER_BYTES;
|
|
45911
|
+
let imageData = false;
|
|
45912
|
+
let ended = false;
|
|
45913
|
+
while (offset + PNG_CHUNK_OVERHEAD <= buffer.length) {
|
|
45914
|
+
const length = buffer.readUInt32BE(offset);
|
|
45915
|
+
const type = buffer.toString("ascii", offset + 4, offset + 8);
|
|
45916
|
+
const next = offset + PNG_CHUNK_OVERHEAD + length;
|
|
45917
|
+
if (next > buffer.length || type === "IHDR") throw new DeviceScreenshotFailure({ message: "Invalid PNG chunk." });
|
|
45918
|
+
if (type === "IDAT") imageData = true;
|
|
45919
|
+
if (type === "IEND") {
|
|
45920
|
+
ended = length === 0 && next === buffer.length;
|
|
45921
|
+
break;
|
|
45922
|
+
}
|
|
45923
|
+
offset = next;
|
|
45924
|
+
}
|
|
45925
|
+
if (!imageData || !ended) throw new DeviceScreenshotFailure({ message: "Incomplete PNG screenshot." });
|
|
45926
|
+
return {
|
|
45927
|
+
width,
|
|
45928
|
+
height
|
|
45929
|
+
};
|
|
45930
|
+
}
|
|
45931
|
+
const make$82 = Effect.fn("DeviceScreenshot.make")(function* () {
|
|
45932
|
+
const http = yield* HttpClient.HttpClient;
|
|
45933
|
+
return Effect.fn("DeviceScreenshot.capture")(function* (ready, session) {
|
|
45934
|
+
const origin = yield* Effect.try(() => new URL(ready.hub.origin));
|
|
45935
|
+
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." });
|
|
45936
|
+
const vendor = session.platform === "ios" ? "serve-sim" : "serve-emu";
|
|
45937
|
+
const response = yield* http.execute(HttpClientRequest.post(`${origin.origin}/vendor/${vendor}/api/screenshot?device=${encodeURIComponent(session.deviceId)}`));
|
|
45938
|
+
if (response.status !== 200) return yield* new DeviceScreenshotFailure({ message: "Screenshot rejected." });
|
|
45939
|
+
let bytes = 0;
|
|
45940
|
+
const chunks = [];
|
|
45941
|
+
yield* response.stream.pipe(Stream.runForEach((chunk) => Effect.gen(function* () {
|
|
45942
|
+
bytes += chunk.byteLength;
|
|
45943
|
+
if (bytes > 8388608) return yield* new DeviceScreenshotFailure({ message: "Screenshot too large." });
|
|
45944
|
+
chunks.push(chunk);
|
|
45945
|
+
})));
|
|
45946
|
+
const png = Buffer.concat(chunks, bytes);
|
|
45947
|
+
return {
|
|
45948
|
+
png,
|
|
45949
|
+
...yield* Effect.try(() => pngDimensions(png))
|
|
45950
|
+
};
|
|
45951
|
+
}, Effect.scoped, Effect.timeout(Duration.millis(SCREENSHOT_TIMEOUT_MS)), Effect.mapError(() => new DeviceOperationError({
|
|
45952
|
+
operation: "screenshot",
|
|
45953
|
+
reason: "request_failed",
|
|
45954
|
+
cause: "Device screenshot could not be captured."
|
|
45955
|
+
})));
|
|
45956
|
+
});
|
|
45957
|
+
var DeviceScreenshot = class extends Context.Service()("@p4code/cli/device/DeviceScreenshot") {};
|
|
45958
|
+
const layer$72 = Layer.effect(DeviceScreenshot, make$82().pipe(Effect.map((capture) => ({ capture }))));
|
|
45959
|
+
//#endregion
|
|
45960
|
+
//#region src/device/XcodeMcpClient.ts
|
|
45961
|
+
const XCODE_BUILD_MCP_VERSION = "2.7.0";
|
|
45962
|
+
const PROTOCOL_VERSION = "2025-06-18";
|
|
45963
|
+
const REQUEST_TIMEOUT_MS$5 = 6e4;
|
|
45964
|
+
const MAX_MESSAGE_BYTES = 12 * 1024 * 1024;
|
|
45965
|
+
const MAX_TOOL_PAGES = 32;
|
|
45966
|
+
function objectValue(value) {
|
|
45967
|
+
return typeof value === "object" && value !== null && !Array.isArray(value) ? value : {};
|
|
45968
|
+
}
|
|
45969
|
+
/** One process per lease keeps semantic refs and simulator defaults isolated. Never invokes npx. */
|
|
45970
|
+
var XcodeMcpClient = class XcodeMcpClient {
|
|
45971
|
+
child;
|
|
45972
|
+
sequence = 0;
|
|
45973
|
+
buffer = "";
|
|
45974
|
+
closed = false;
|
|
45975
|
+
pending = /* @__PURE__ */ new Map();
|
|
45976
|
+
tools = /* @__PURE__ */ new Set();
|
|
45977
|
+
constructor(child) {
|
|
45978
|
+
this.child = child;
|
|
45979
|
+
child.stdout.setEncoding("utf8");
|
|
45980
|
+
child.stdout.on("data", (chunk) => {
|
|
45981
|
+
this.buffer += chunk;
|
|
45982
|
+
if (Buffer.byteLength(this.buffer) > MAX_MESSAGE_BYTES) {
|
|
45983
|
+
this.close(/* @__PURE__ */ new Error("Device MCP response exceeds the supported size."));
|
|
45984
|
+
return;
|
|
45985
|
+
}
|
|
45986
|
+
let boundary;
|
|
45987
|
+
while ((boundary = this.buffer.indexOf("\n")) >= 0) {
|
|
45988
|
+
const line = this.buffer.slice(0, boundary);
|
|
45989
|
+
this.buffer = this.buffer.slice(boundary + 1);
|
|
45990
|
+
try {
|
|
45991
|
+
const message = objectValue(JSON.parse(line));
|
|
45992
|
+
if (typeof message.id !== "number") continue;
|
|
45993
|
+
const call = this.pending.get(message.id);
|
|
45994
|
+
if (!call) continue;
|
|
45995
|
+
this.pending.delete(message.id);
|
|
45996
|
+
if (message.error) {
|
|
45997
|
+
const detail = objectValue(message.error).message;
|
|
45998
|
+
call.reject(new Error(typeof detail === "string" ? detail : "Device MCP request failed."));
|
|
45999
|
+
} else call.resolve(message.result);
|
|
46000
|
+
} catch {
|
|
46001
|
+
this.close(/* @__PURE__ */ new Error("Device MCP returned invalid stdio JSON."));
|
|
46002
|
+
return;
|
|
46003
|
+
}
|
|
46004
|
+
}
|
|
46005
|
+
});
|
|
46006
|
+
child.stderr.resume();
|
|
46007
|
+
child.on("error", () => this.close(/* @__PURE__ */ new Error("Device MCP executable could not start.")));
|
|
46008
|
+
child.on("exit", () => this.close(/* @__PURE__ */ new Error("Device MCP disconnected. Select the device again.")));
|
|
46009
|
+
child.stdin.on("error", () => this.close(/* @__PURE__ */ new Error("Device MCP input disconnected.")));
|
|
46010
|
+
}
|
|
46011
|
+
static async start(executable, cwd, environment, signal, kind = "legacy") {
|
|
46012
|
+
if (!isAbsolute(executable)) throw new Error("Device MCP requires an absolute executable path.");
|
|
46013
|
+
await access(executable, constants.X_OK).catch(() => {
|
|
46014
|
+
throw new Error(kind === "apple" ? "Selected Xcode bridge is missing or not executable. Check the selected Xcode installation." : "Configured XcodeBuildMCP executable is missing or not executable. Install 2.7.0 explicitly.");
|
|
46015
|
+
});
|
|
46016
|
+
signal.throwIfAborted();
|
|
46017
|
+
const client = new XcodeMcpClient(spawn(executable, kind === "apple" ? ["mcpbridge"] : ["mcp"], {
|
|
46018
|
+
cwd,
|
|
46019
|
+
shell: false,
|
|
46020
|
+
stdio: "pipe",
|
|
46021
|
+
env: {
|
|
46022
|
+
...environment,
|
|
46023
|
+
...kind === "legacy" ? {
|
|
46024
|
+
XCODEBUILDMCP_CWD: cwd,
|
|
46025
|
+
XCODEBUILDMCP_DISABLE_SESSION_DEFAULTS: "true",
|
|
46026
|
+
XCODEBUILDMCP_ENABLED_WORKFLOWS: "simulator,ui-automation",
|
|
46027
|
+
XCODEBUILDMCP_SENTRY_DISABLED: "true"
|
|
46028
|
+
} : {}
|
|
46029
|
+
}
|
|
46030
|
+
}));
|
|
46031
|
+
try {
|
|
46032
|
+
const initialized = objectValue(await client.request("initialize", {
|
|
46033
|
+
protocolVersion: PROTOCOL_VERSION,
|
|
46034
|
+
capabilities: {},
|
|
46035
|
+
clientInfo: {
|
|
46036
|
+
name: "p4code-device-adapter",
|
|
46037
|
+
version: "1"
|
|
46038
|
+
}
|
|
46039
|
+
}, signal));
|
|
46040
|
+
if (kind === "apple" && objectValue(initialized.serverInfo).name !== "xcode-tools") throw new Error("Selected Xcode did not expose Apple MCP tools.");
|
|
46041
|
+
if (kind === "legacy" && objectValue(initialized.serverInfo).version !== "2.7.0") throw new Error(`P4 requires XcodeBuildMCP ${XCODE_BUILD_MCP_VERSION}; configured executable reported a different version.`);
|
|
46042
|
+
client.child.stdin.write(JSON.stringify({
|
|
46043
|
+
jsonrpc: "2.0",
|
|
46044
|
+
method: "notifications/initialized"
|
|
46045
|
+
}) + "\n");
|
|
46046
|
+
let cursor;
|
|
46047
|
+
const cursors = /* @__PURE__ */ new Set();
|
|
46048
|
+
do {
|
|
46049
|
+
const page = objectValue(await client.request("tools/list", cursor ? { cursor } : {}, signal));
|
|
46050
|
+
if (!Array.isArray(page.tools)) throw new Error("Device MCP did not advertise tools.");
|
|
46051
|
+
for (const tool of page.tools) {
|
|
46052
|
+
const name = objectValue(tool).name;
|
|
46053
|
+
if (typeof name === "string") client.tools.add(name);
|
|
46054
|
+
}
|
|
46055
|
+
cursor = page.nextCursor;
|
|
46056
|
+
if (typeof cursor === "string" && cursor.length > 0) {
|
|
46057
|
+
if (cursors.has(cursor) || cursors.size >= MAX_TOOL_PAGES) throw new Error("Device MCP tool discovery did not finish within its page limit.");
|
|
46058
|
+
cursors.add(cursor);
|
|
46059
|
+
}
|
|
46060
|
+
} while (typeof cursor === "string" && cursor.length > 0);
|
|
46061
|
+
return client;
|
|
46062
|
+
} catch (error) {
|
|
46063
|
+
client.close();
|
|
46064
|
+
throw error;
|
|
46065
|
+
}
|
|
46066
|
+
}
|
|
46067
|
+
request(method, params, signal) {
|
|
46068
|
+
signal.throwIfAborted();
|
|
46069
|
+
if (this.closed) return Promise.reject(/* @__PURE__ */ new Error("Device MCP session is closed. Select the device again."));
|
|
46070
|
+
const id = ++this.sequence;
|
|
46071
|
+
return new Promise((resolve, reject) => {
|
|
46072
|
+
const abort = () => this.close(/* @__PURE__ */ new Error("Device MCP request cancelled. Select the device again."));
|
|
46073
|
+
const timer = setTimeout(() => this.close(/* @__PURE__ */ new Error("Device MCP timed out. Select the device again.")), REQUEST_TIMEOUT_MS$5);
|
|
46074
|
+
const finish = () => {
|
|
46075
|
+
clearTimeout(timer);
|
|
46076
|
+
signal.removeEventListener("abort", abort);
|
|
46077
|
+
};
|
|
46078
|
+
this.pending.set(id, {
|
|
46079
|
+
resolve: (result) => {
|
|
46080
|
+
finish();
|
|
46081
|
+
resolve(result);
|
|
46082
|
+
},
|
|
46083
|
+
reject: (error) => {
|
|
46084
|
+
finish();
|
|
46085
|
+
reject(error);
|
|
46086
|
+
}
|
|
46087
|
+
});
|
|
46088
|
+
signal.addEventListener("abort", abort, { once: true });
|
|
46089
|
+
this.child.stdin.write(JSON.stringify({
|
|
46090
|
+
jsonrpc: "2.0",
|
|
46091
|
+
id,
|
|
46092
|
+
method,
|
|
46093
|
+
params
|
|
46094
|
+
}) + "\n");
|
|
46095
|
+
});
|
|
46096
|
+
}
|
|
46097
|
+
async call(name, args, signal) {
|
|
46098
|
+
if (!this.tools.has(name)) throw new Error(`Selected device MCP service does not expose ${name}. Check adapter capabilities and Xcode setup.`);
|
|
46099
|
+
const redact = (error) => {
|
|
46100
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
46101
|
+
for (const [key, value] of Object.entries(args)) if (/sessionkey$/i.test(key) && typeof value === "string" && value.length > 0) message = message.replaceAll(value, "[redacted]");
|
|
46102
|
+
return new Error(message);
|
|
46103
|
+
};
|
|
46104
|
+
try {
|
|
46105
|
+
const result = objectValue(await this.request("tools/call", {
|
|
46106
|
+
name,
|
|
46107
|
+
arguments: args
|
|
46108
|
+
}, signal));
|
|
46109
|
+
const structured = objectValue(result.structuredContent);
|
|
46110
|
+
if (result.isError === true || structured.didError === true) {
|
|
46111
|
+
const detail = (Array.isArray(result.content) ? result.content : []).map((part) => objectValue(part).text).filter((part) => typeof part === "string").join("\n");
|
|
46112
|
+
throw new Error(detail || String(structured.error ?? `${name} failed. Refresh device state before retrying.`));
|
|
46113
|
+
}
|
|
46114
|
+
return result;
|
|
46115
|
+
} catch (error) {
|
|
46116
|
+
throw redact(error);
|
|
46117
|
+
}
|
|
46118
|
+
}
|
|
46119
|
+
close(error = /* @__PURE__ */ new Error("Device MCP session closed.")) {
|
|
46120
|
+
if (this.closed) return;
|
|
46121
|
+
this.closed = true;
|
|
46122
|
+
for (const call of this.pending.values()) call.reject(error);
|
|
46123
|
+
this.pending.clear();
|
|
46124
|
+
this.child.kill("SIGTERM");
|
|
46125
|
+
}
|
|
46126
|
+
};
|
|
46127
|
+
//#endregion
|
|
46128
|
+
//#region src/device/XcodeDeviceAdapter.ts
|
|
46129
|
+
const SimulatorList = Schema$1.Struct({ simulators: Schema$1.Array(Schema$1.Struct({
|
|
46130
|
+
simulatorId: Schema$1.String,
|
|
46131
|
+
name: Schema$1.String,
|
|
46132
|
+
runtime: Schema$1.String,
|
|
46133
|
+
state: Schema$1.String,
|
|
46134
|
+
isAvailable: Schema$1.Boolean
|
|
46135
|
+
})) });
|
|
46136
|
+
const decodeSimulators = Schema$1.decodeUnknownSync(SimulatorList);
|
|
46137
|
+
const MAX_LEASES = 32;
|
|
46138
|
+
const Frame = Schema$1.Struct({
|
|
46139
|
+
x: Schema$1.Number,
|
|
46140
|
+
y: Schema$1.Number,
|
|
46141
|
+
width: Schema$1.Number,
|
|
46142
|
+
height: Schema$1.Number
|
|
46143
|
+
});
|
|
46144
|
+
const Snapshot = Schema$1.Struct({ elements: Schema$1.Array(Schema$1.Struct({
|
|
46145
|
+
ref: Schema$1.String,
|
|
46146
|
+
role: Schema$1.optional(Schema$1.String),
|
|
46147
|
+
frame: Frame
|
|
46148
|
+
})) });
|
|
46149
|
+
const readSnapshot = Schema$1.decodeUnknownOption(Snapshot);
|
|
46150
|
+
/** Retain structured semantic snapshots; callers never need screenshot round trips for refs. */
|
|
46151
|
+
function xcodeResultData(result) {
|
|
46152
|
+
const structured = objectValue(result.structuredContent);
|
|
46153
|
+
return objectValue(structured.data ?? structured);
|
|
46154
|
+
}
|
|
46155
|
+
function createXcodeDeviceAdapter(executable, cwd, environment) {
|
|
46156
|
+
const clients = /* @__PURE__ */ new Map();
|
|
46157
|
+
const recordings = /* @__PURE__ */ new Map();
|
|
46158
|
+
const snapshots = /* @__PURE__ */ new Map();
|
|
46159
|
+
const remember = (session, data) => {
|
|
46160
|
+
const snapshot = readSnapshot(data.capture);
|
|
46161
|
+
if (snapshot._tag === "Some") snapshots.set(session.leaseId, snapshot.value);
|
|
46162
|
+
const viewport = snapshots.get(session.leaseId)?.elements.find((element) => element.role === "window")?.frame;
|
|
46163
|
+
return {
|
|
46164
|
+
...data,
|
|
46165
|
+
...viewport ? { viewport } : {}
|
|
46166
|
+
};
|
|
46167
|
+
};
|
|
46168
|
+
const get = async (key, signal) => {
|
|
46169
|
+
let pending = clients.get(key);
|
|
46170
|
+
if (!pending) {
|
|
46171
|
+
if (clients.size >= MAX_LEASES) throw new Error("Close an existing Xcode device session before opening another.");
|
|
46172
|
+
pending = XcodeMcpClient.start(executable, cwd, environment, signal);
|
|
46173
|
+
clients.set(key, pending);
|
|
46174
|
+
pending.catch(() => {
|
|
46175
|
+
if (clients.get(key) === pending) clients.delete(key);
|
|
46176
|
+
});
|
|
46177
|
+
}
|
|
46178
|
+
return pending;
|
|
46179
|
+
};
|
|
46180
|
+
const run = (operation, execute) => Effect.tryPromise({
|
|
46181
|
+
try: execute,
|
|
46182
|
+
catch: (cause) => new DeviceOperationError({
|
|
46183
|
+
operation,
|
|
46184
|
+
reason: "request_failed",
|
|
46185
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
46186
|
+
})
|
|
46187
|
+
});
|
|
46188
|
+
const forSession = async (session, signal) => {
|
|
46189
|
+
if (session.hostId !== "local" || session.platform !== "ios" || !session.leaseId) throw new Error("Xcode adapter requires an exact local iOS Simulator lease.");
|
|
46190
|
+
return get(session.leaseId, signal);
|
|
46191
|
+
};
|
|
46192
|
+
const closeSession = (leaseId) => {
|
|
46193
|
+
const client = clients.get(leaseId);
|
|
46194
|
+
clients.delete(leaseId);
|
|
46195
|
+
const recording = recordings.get(leaseId);
|
|
46196
|
+
recordings.delete(leaseId);
|
|
46197
|
+
snapshots.delete(leaseId);
|
|
46198
|
+
client?.then(async (client) => {
|
|
46199
|
+
try {
|
|
46200
|
+
if (recording) await client.call("record_sim_video", {
|
|
46201
|
+
...recording,
|
|
46202
|
+
stop: true
|
|
46203
|
+
}, new AbortController().signal);
|
|
46204
|
+
} finally {
|
|
46205
|
+
client.close();
|
|
46206
|
+
}
|
|
46207
|
+
}).catch(() => {});
|
|
46208
|
+
};
|
|
46209
|
+
return {
|
|
46210
|
+
discover: run("list", async (signal) => {
|
|
46211
|
+
const client = await get("discovery", signal);
|
|
46212
|
+
return decodeSimulators(xcodeResultData(await client.call("list_sims", {}, signal))).simulators.filter((sim) => sim.isAvailable && /iOS/i.test(sim.runtime)).map((sim) => ({
|
|
46213
|
+
id: sim.simulatorId,
|
|
46214
|
+
hostId: "local",
|
|
46215
|
+
name: sim.name,
|
|
46216
|
+
version: sim.runtime,
|
|
46217
|
+
booted: sim.state === "Booted",
|
|
46218
|
+
physical: false,
|
|
46219
|
+
platform: "ios"
|
|
46220
|
+
}));
|
|
46221
|
+
}),
|
|
46222
|
+
state: (session, sinceScreenHash) => run("state", async (signal) => {
|
|
46223
|
+
const client = await forSession(session, signal);
|
|
46224
|
+
const data = xcodeResultData(await client.call("snapshot_ui", {
|
|
46225
|
+
simulatorId: session.deviceId,
|
|
46226
|
+
...sinceScreenHash ? { sinceScreenHash } : {}
|
|
46227
|
+
}, signal));
|
|
46228
|
+
return {
|
|
46229
|
+
adapter: "xcodebuildmcp",
|
|
46230
|
+
capabilities: [...client.tools].filter((tool) => [
|
|
46231
|
+
"tap",
|
|
46232
|
+
"type_text",
|
|
46233
|
+
"swipe",
|
|
46234
|
+
"drag",
|
|
46235
|
+
"batch",
|
|
46236
|
+
"snapshot_ui",
|
|
46237
|
+
"screenshot",
|
|
46238
|
+
"record_sim_video"
|
|
46239
|
+
].includes(tool)),
|
|
46240
|
+
...remember(session, data)
|
|
46241
|
+
};
|
|
46242
|
+
}),
|
|
46243
|
+
action: (session, input) => run("command", async (signal) => {
|
|
46244
|
+
const client = await forSession(session, signal);
|
|
46245
|
+
const { action, ...parameters } = input;
|
|
46246
|
+
const snapshot = snapshots.get(session.leaseId);
|
|
46247
|
+
const ref = input.action === "batch" ? input.steps.at(-1)?.elementRef : input.action === "swipe" ? input.withinElementRef : input.elementRef;
|
|
46248
|
+
const bounds = snapshot?.elements.find((element) => element.ref === ref)?.frame;
|
|
46249
|
+
const viewport = snapshot?.elements.find((element) => element.role === "window")?.frame;
|
|
46250
|
+
const data = xcodeResultData(await client.call(action, {
|
|
46251
|
+
...parameters,
|
|
46252
|
+
simulatorId: session.deviceId
|
|
46253
|
+
}, signal));
|
|
46254
|
+
return {
|
|
46255
|
+
...remember(session, data),
|
|
46256
|
+
...bounds && viewport && viewport.width > 0 && viewport.height > 0 ? { pointer: {
|
|
46257
|
+
x: (bounds.x + bounds.width / 2 - viewport.x) / viewport.width,
|
|
46258
|
+
y: (bounds.y + bounds.height / 2 - viewport.y) / viewport.height
|
|
46259
|
+
} } : {}
|
|
46260
|
+
};
|
|
46261
|
+
}),
|
|
46262
|
+
screenshot: (session) => run("screenshot", async (signal) => {
|
|
46263
|
+
const result = await (await forSession(session, signal)).call("screenshot", {
|
|
46264
|
+
simulatorId: session.deviceId,
|
|
46265
|
+
returnFormat: "base64"
|
|
46266
|
+
}, signal);
|
|
46267
|
+
const image = (Array.isArray(result.content) ? result.content : []).map(objectValue).find((part) => part.type === "image" && part.mimeType === "image/png");
|
|
46268
|
+
if (typeof image?.data !== "string") throw new Error("XcodeBuildMCP did not return a PNG screenshot.");
|
|
46269
|
+
const png = Buffer.from(image.data, "base64");
|
|
46270
|
+
return {
|
|
46271
|
+
png,
|
|
46272
|
+
...pngDimensions(png)
|
|
46273
|
+
};
|
|
46274
|
+
}),
|
|
46275
|
+
recording: (session, action) => run("recording", async (signal) => {
|
|
46276
|
+
const client = await forSession(session, signal);
|
|
46277
|
+
const key = session.leaseId;
|
|
46278
|
+
if (action === "start" && recordings.has(key)) throw new Error("This device session is already recording.");
|
|
46279
|
+
if (action === "stop" && !recordings.has(key)) throw new Error("This device session has no active recording.");
|
|
46280
|
+
const outputFile = recordings.get(key)?.outputFile ?? `${cwd}/device-recording-${randomUUID()}.mp4`;
|
|
46281
|
+
const result = xcodeResultData(await client.call("record_sim_video", {
|
|
46282
|
+
simulatorId: session.deviceId,
|
|
46283
|
+
...action === "start" ? { start: true } : {
|
|
46284
|
+
stop: true,
|
|
46285
|
+
outputFile
|
|
46286
|
+
}
|
|
46287
|
+
}, signal));
|
|
46288
|
+
if (action === "start") recordings.set(key, {
|
|
46289
|
+
outputFile,
|
|
46290
|
+
simulatorId: session.deviceId
|
|
46291
|
+
});
|
|
46292
|
+
else recordings.delete(key);
|
|
46293
|
+
return result;
|
|
46294
|
+
}),
|
|
46295
|
+
closeSession,
|
|
46296
|
+
stop: () => {
|
|
46297
|
+
for (const key of clients.keys()) closeSession(key);
|
|
46298
|
+
}
|
|
46299
|
+
};
|
|
46300
|
+
}
|
|
46301
|
+
//#endregion
|
|
46302
|
+
//#region src/device/AppleDeviceAdapter.ts
|
|
46303
|
+
const MAX_HIERARCHY_BYTES = 512 * 1024;
|
|
46304
|
+
const MAX_SESSIONS = 32;
|
|
46305
|
+
const REQUIRED_DEVICE_TOOLS = [
|
|
46306
|
+
"DeviceInteractionStartSession",
|
|
46307
|
+
"DeviceInteractionSynthesize",
|
|
46308
|
+
"DeviceInteractionEndSession"
|
|
46309
|
+
];
|
|
46310
|
+
const FRAME_PATTERN = /\{\{(-?[\d.]+),\s*(-?[\d.]+)\},\s*\{([\d.]+),\s*([\d.]+)\}\}/;
|
|
46311
|
+
const HIT_PATTERN = /hitPoint:\s*\{(-?[\d.]+),\s*(-?[\d.]+)\}/;
|
|
46312
|
+
const Capture = Schema$1.Struct({
|
|
46313
|
+
hierarchyPath: Schema$1.String,
|
|
46314
|
+
screenshotPath: Schema$1.String
|
|
46315
|
+
});
|
|
46316
|
+
const Session = Schema$1.Struct({
|
|
46317
|
+
interactionSessionKey: Schema$1.String,
|
|
46318
|
+
deviceUUID: Schema$1.String,
|
|
46319
|
+
deviceIsSimulator: Schema$1.Boolean
|
|
46320
|
+
});
|
|
46321
|
+
const Simulators = Schema$1.Struct({ devices: Schema$1.Record(Schema$1.String, Schema$1.Array(Schema$1.Struct({
|
|
46322
|
+
udid: Schema$1.String,
|
|
46323
|
+
name: Schema$1.String,
|
|
46324
|
+
state: Schema$1.String,
|
|
46325
|
+
isAvailable: Schema$1.Boolean
|
|
46326
|
+
}))) });
|
|
46327
|
+
function appleMcpData(result) {
|
|
46328
|
+
if (result.structuredContent) return objectValue(result.structuredContent);
|
|
46329
|
+
for (const block of Array.isArray(result.content) ? result.content : []) {
|
|
46330
|
+
const text = objectValue(block).text;
|
|
46331
|
+
if (typeof text !== "string") continue;
|
|
46332
|
+
try {
|
|
46333
|
+
return objectValue(JSON.parse(text));
|
|
46334
|
+
} catch {}
|
|
46335
|
+
}
|
|
46336
|
+
throw new Error("Apple MCP returned no structured device result.");
|
|
46337
|
+
}
|
|
46338
|
+
/** Use Apple's documented hierarchy hit points, never guessed screenshot coordinates. */
|
|
46339
|
+
function appleHierarchySnapshot(text, sequence) {
|
|
46340
|
+
const elements = text.split("\n").flatMap((line, index) => {
|
|
46341
|
+
const frame = line.match(FRAME_PATTERN);
|
|
46342
|
+
const hit = line.match(HIT_PATTERN);
|
|
46343
|
+
if (!frame || !hit || line.includes("isRemoteLeafPlaceholder")) return [];
|
|
46344
|
+
const [x, y, width, height] = frame.slice(1).map(Number);
|
|
46345
|
+
const [hx, hy] = hit.slice(1).map(Number);
|
|
46346
|
+
if (![
|
|
46347
|
+
x,
|
|
46348
|
+
y,
|
|
46349
|
+
width,
|
|
46350
|
+
height,
|
|
46351
|
+
hx,
|
|
46352
|
+
hy
|
|
46353
|
+
].every((value) => value !== void 0 && Number.isFinite(value)) || width <= 0 || height <= 0) return [];
|
|
46354
|
+
return [{
|
|
46355
|
+
ref: `a${sequence}-${index}`,
|
|
46356
|
+
label: line.trim(),
|
|
46357
|
+
frame: {
|
|
46358
|
+
x,
|
|
46359
|
+
y,
|
|
46360
|
+
width,
|
|
46361
|
+
height
|
|
46362
|
+
},
|
|
46363
|
+
hitPoint: {
|
|
46364
|
+
x: hx,
|
|
46365
|
+
y: hy
|
|
46366
|
+
},
|
|
46367
|
+
role: /\b(?:UI)?Window\b/.test(line) ? "window" : "element",
|
|
46368
|
+
actions: ["tap"]
|
|
46369
|
+
}];
|
|
46370
|
+
});
|
|
46371
|
+
return {
|
|
46372
|
+
screenHash: createHash("sha256").update(text).digest("hex"),
|
|
46373
|
+
seq: sequence,
|
|
46374
|
+
elements
|
|
46375
|
+
};
|
|
46376
|
+
}
|
|
46377
|
+
function createAppleDeviceAdapter(input) {
|
|
46378
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
46379
|
+
const fail = (operation) => (cause) => new DeviceOperationError({
|
|
46380
|
+
operation,
|
|
46381
|
+
reason: "request_failed",
|
|
46382
|
+
cause: cause instanceof Error ? cause.message : String(cause)
|
|
46383
|
+
});
|
|
46384
|
+
const call = (client, name, args) => Effect.tryPromise({
|
|
46385
|
+
try: (signal) => client.call(name, args, signal),
|
|
46386
|
+
catch: fail(name)
|
|
46387
|
+
});
|
|
46388
|
+
const closeSession = (leaseId) => {
|
|
46389
|
+
const pending = sessions.get(leaseId);
|
|
46390
|
+
sessions.delete(leaseId);
|
|
46391
|
+
pending?.then(async (owned) => {
|
|
46392
|
+
try {
|
|
46393
|
+
await owned.client.call("DeviceInteractionEndSession", { interactionSessionKey: owned.key }, new AbortController().signal);
|
|
46394
|
+
} finally {
|
|
46395
|
+
owned.client.close();
|
|
46396
|
+
}
|
|
46397
|
+
}).catch(() => {});
|
|
46398
|
+
};
|
|
46399
|
+
const get = (session) => Effect.tryPromise({
|
|
46400
|
+
try: async (signal) => {
|
|
46401
|
+
if (session.hostId !== "local" || session.platform !== "ios" || !session.leaseId) throw new Error("Apple MCP requires an exact local iOS device lease.");
|
|
46402
|
+
let pending = sessions.get(session.leaseId);
|
|
46403
|
+
if (!pending) {
|
|
46404
|
+
if (sessions.size >= MAX_SESSIONS) throw new Error("Close an existing device session first.");
|
|
46405
|
+
pending = (async () => {
|
|
46406
|
+
const client = await XcodeMcpClient.start("/usr/bin/xcrun", input.cwd, {
|
|
46407
|
+
...input.environment,
|
|
46408
|
+
MCP_XCODE_SESSION_ID: randomUUID()
|
|
46409
|
+
}, signal, "apple");
|
|
46410
|
+
try {
|
|
46411
|
+
const missing = REQUIRED_DEVICE_TOOLS.filter((tool) => !client.tools.has(tool));
|
|
46412
|
+
if (missing.length > 0) throw new Error(`Selected Xcode lacks required device tools: ${missing.join(", ")}. No device session was opened.`);
|
|
46413
|
+
if (input.workspacePath) await client.call("XcodeOpenWorkspace", { path: input.workspacePath }, signal);
|
|
46414
|
+
const opened = Schema$1.decodeUnknownSync(Session)(appleMcpData(await client.call("DeviceInteractionStartSession", {
|
|
46415
|
+
deviceIdentifier: session.deviceId,
|
|
46416
|
+
sessionIdentifier: `P4 Device ${session.threadId.slice(0, 8)}`
|
|
46417
|
+
}, signal)));
|
|
46418
|
+
if (opened.deviceUUID.toLowerCase() !== session.deviceId.toLowerCase() || !opened.deviceIsSimulator) {
|
|
46419
|
+
await client.call("DeviceInteractionEndSession", { interactionSessionKey: opened.interactionSessionKey }, signal);
|
|
46420
|
+
throw new Error("Apple selected a different device. No interaction was performed.");
|
|
46421
|
+
}
|
|
46422
|
+
return {
|
|
46423
|
+
client,
|
|
46424
|
+
key: opened.interactionSessionKey,
|
|
46425
|
+
sequence: 0
|
|
46426
|
+
};
|
|
46427
|
+
} catch (error) {
|
|
46428
|
+
client.close();
|
|
46429
|
+
throw error;
|
|
46430
|
+
}
|
|
46431
|
+
})();
|
|
46432
|
+
sessions.set(session.leaseId, pending);
|
|
46433
|
+
const leaseId = session.leaseId;
|
|
46434
|
+
pending.catch(() => {
|
|
46435
|
+
if (sessions.get(leaseId) === pending) sessions.delete(leaseId);
|
|
46436
|
+
});
|
|
46437
|
+
}
|
|
46438
|
+
return pending;
|
|
46439
|
+
},
|
|
46440
|
+
catch: fail("open")
|
|
46441
|
+
});
|
|
46442
|
+
const capture = (owned, interactionCommand) => Effect.gen(function* () {
|
|
46443
|
+
const response = yield* call(owned.client, "DeviceInteractionSynthesize", {
|
|
46444
|
+
interactSessionKey: owned.key,
|
|
46445
|
+
...interactionCommand ? { interactionCommand } : {}
|
|
46446
|
+
});
|
|
46447
|
+
const data = yield* Effect.try({
|
|
46448
|
+
try: () => appleMcpData(response),
|
|
46449
|
+
catch: fail("state")
|
|
46450
|
+
});
|
|
46451
|
+
const result = yield* Schema$1.decodeUnknownEffect(Capture)(data);
|
|
46452
|
+
if ((yield* input.fs.stat(result.hierarchyPath)).size > BigInt(MAX_HIERARCHY_BYTES)) return yield* fail("state")("Apple hierarchy exceeds the supported size.");
|
|
46453
|
+
const snapshot = appleHierarchySnapshot(yield* input.fs.readFileString(result.hierarchyPath), owned.sequence + 1);
|
|
46454
|
+
if (owned.snapshot?.screenHash !== snapshot.screenHash) {
|
|
46455
|
+
owned.snapshot = snapshot;
|
|
46456
|
+
owned.sequence += 1;
|
|
46457
|
+
}
|
|
46458
|
+
const currentSnapshot = owned.snapshot;
|
|
46459
|
+
owned.image = result.screenshotPath;
|
|
46460
|
+
const viewport = currentSnapshot.elements.find((element) => element.role === "window")?.frame;
|
|
46461
|
+
return {
|
|
46462
|
+
adapter: "apple-xcode",
|
|
46463
|
+
capabilities: [
|
|
46464
|
+
"snapshot_ui",
|
|
46465
|
+
"tap",
|
|
46466
|
+
"screenshot"
|
|
46467
|
+
],
|
|
46468
|
+
capture: currentSnapshot,
|
|
46469
|
+
...viewport ? { viewport } : {}
|
|
46470
|
+
};
|
|
46471
|
+
}).pipe(Effect.mapError(fail("state")));
|
|
46472
|
+
return {
|
|
46473
|
+
diagnose: Effect.gen(function* () {
|
|
46474
|
+
const result = yield* input.run("xcrun", [
|
|
46475
|
+
"mcp-server",
|
|
46476
|
+
"status",
|
|
46477
|
+
"--format",
|
|
46478
|
+
"json"
|
|
46479
|
+
]);
|
|
46480
|
+
if (result.code !== 0) return "Apple MCP did not respond. Check the selected Xcode installation and MCP service.";
|
|
46481
|
+
const status = objectValue(yield* Schema$1.decodeUnknownEffect(Schema$1.UnknownFromJsonString)(result.stdout));
|
|
46482
|
+
const permission = objectValue(status.permission);
|
|
46483
|
+
if ((Array.isArray(permission.pendingAgentApprovals) ? permission.pendingAgentApprovals : []).some((item) => objectValue(objectValue(objectValue(objectValue(item).subject).agent)._0).name === "p4code-device-adapter")) return "Apple Xcode is waiting for approval of p4code-device-adapter and its project folder. Approve the pending request in Xcode, then select the device again. P4 cannot grant this approval automatically.";
|
|
46484
|
+
if (status.running === false) return "Apple MCP service is not running. Open the selected Xcode project or configure its headless service, then select the device again.";
|
|
46485
|
+
return "Apple MCP did not respond in time. Check Xcode agent/folder permissions and session logs before selecting the device again.";
|
|
46486
|
+
}).pipe(Effect.orElseSucceed(() => "Apple MCP did not respond. Check Xcode agent/folder permissions and service status.")),
|
|
46487
|
+
discover: Effect.gen(function* () {
|
|
46488
|
+
const result = yield* input.run("xcrun", [
|
|
46489
|
+
"simctl",
|
|
46490
|
+
"list",
|
|
46491
|
+
"devices",
|
|
46492
|
+
"available",
|
|
46493
|
+
"--json"
|
|
46494
|
+
]);
|
|
46495
|
+
if (result.code !== 0) return yield* fail("list")("Selected Xcode cannot list simulators.");
|
|
46496
|
+
const parsed = yield* Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(Simulators))(result.stdout).pipe(Effect.mapError(fail("list")));
|
|
46497
|
+
return Object.entries(parsed.devices).filter(([runtime]) => runtime.includes(".iOS-")).flatMap(([runtime, devices]) => devices.filter((device) => device.isAvailable).map((device) => ({
|
|
46498
|
+
hostId: "local",
|
|
46499
|
+
id: device.udid,
|
|
46500
|
+
platform: "ios",
|
|
46501
|
+
name: device.name,
|
|
46502
|
+
version: runtime.replace("com.apple.CoreSimulator.SimRuntime.", "").replaceAll("-", "."),
|
|
46503
|
+
physical: false,
|
|
46504
|
+
booted: device.state === "Booted"
|
|
46505
|
+
})));
|
|
46506
|
+
}),
|
|
46507
|
+
state: (session, sinceScreenHash) => Effect.gen(function* () {
|
|
46508
|
+
const result = yield* capture(yield* get(session));
|
|
46509
|
+
return sinceScreenHash === result.capture.screenHash ? {
|
|
46510
|
+
...result,
|
|
46511
|
+
capture: {
|
|
46512
|
+
screenHash: result.capture.screenHash,
|
|
46513
|
+
seq: result.capture.seq,
|
|
46514
|
+
unchanged: true
|
|
46515
|
+
}
|
|
46516
|
+
} : result;
|
|
46517
|
+
}),
|
|
46518
|
+
action: (session, action) => Effect.gen(function* () {
|
|
46519
|
+
if (action.action !== "tap") return yield* fail("command")("This Apple MCP integration currently advertises tap only. Use only capabilities returned by getAXState().");
|
|
46520
|
+
const owned = yield* get(session);
|
|
46521
|
+
const previous = owned.snapshot;
|
|
46522
|
+
const element = previous?.elements.find((element) => element.ref === action.elementRef);
|
|
46523
|
+
if (!element) return yield* fail("command")("Stale device ref. Read getAXState() and choose a current element.");
|
|
46524
|
+
const fresh = yield* capture(owned);
|
|
46525
|
+
if (fresh.capture.screenHash !== previous.screenHash) return yield* fail("command")("Device layout changed. Read getAXState() and choose a current element; no action was performed.");
|
|
46526
|
+
return {
|
|
46527
|
+
...yield* capture(owned, `t ${element.hitPoint.x} ${element.hitPoint.y}`),
|
|
46528
|
+
...fresh.viewport ? { pointer: {
|
|
46529
|
+
x: (element.hitPoint.x - fresh.viewport.x) / fresh.viewport.width,
|
|
46530
|
+
y: (element.hitPoint.y - fresh.viewport.y) / fresh.viewport.height
|
|
46531
|
+
} } : {}
|
|
46532
|
+
};
|
|
46533
|
+
}),
|
|
46534
|
+
screenshot: (session) => Effect.gen(function* () {
|
|
46535
|
+
const owned = yield* get(session);
|
|
46536
|
+
yield* capture(owned);
|
|
46537
|
+
if ((yield* input.fs.stat(owned.image)).size > BigInt(8388608)) return yield* fail("screenshot")("Apple screenshot exceeds the supported size.");
|
|
46538
|
+
const png = Buffer.from(yield* input.fs.readFile(owned.image));
|
|
46539
|
+
return {
|
|
46540
|
+
png,
|
|
46541
|
+
...yield* Effect.try({
|
|
46542
|
+
try: () => pngDimensions(png),
|
|
46543
|
+
catch: fail("screenshot")
|
|
46544
|
+
})
|
|
46545
|
+
};
|
|
46546
|
+
}).pipe(Effect.mapError(fail("screenshot"))),
|
|
46547
|
+
recording: (_session, _action) => Effect.fail(fail("recording")("Apple MCP does not advertise a recording tool. Recording is unavailable through this adapter.")),
|
|
46548
|
+
closeSession,
|
|
46549
|
+
stop: () => {
|
|
46550
|
+
for (const key of sessions.keys()) closeSession(key);
|
|
46551
|
+
}
|
|
46552
|
+
};
|
|
46553
|
+
}
|
|
46554
|
+
//#endregion
|
|
45606
46555
|
//#region src/device/DeviceToolchain.ts
|
|
45607
46556
|
/**
|
|
45608
46557
|
* Pinned installs of the two external tools device support is built on.
|
|
@@ -45818,6 +46767,7 @@ function deviceHubPlatform(platforms) {
|
|
|
45818
46767
|
const COMMAND_TIMEOUT_MS$1 = 2e4;
|
|
45819
46768
|
const COMMAND_OUTPUT_LIMIT = 1024 * 1024;
|
|
45820
46769
|
const COMMAND_FAILURE_CODE = 127;
|
|
46770
|
+
const APPLE_DEVICE_MCP_MINIMUM_XCODE = 27;
|
|
45821
46771
|
const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
45822
46772
|
const config = yield* ServerConfig$1;
|
|
45823
46773
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -45864,7 +46814,19 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
|
45864
46814
|
stderr: "Device command failed.",
|
|
45865
46815
|
code: COMMAND_FAILURE_CODE
|
|
45866
46816
|
})));
|
|
46817
|
+
const appleVersion = (platform === "darwin" ? yield* run("xcrun", ["--find", "mcpbridge"]) : null)?.code === 0 ? yield* run("xcodebuild", ["-version"]) : null;
|
|
46818
|
+
const appleAvailable = appleVersion?.code === 0 && Number(appleVersion.stdout.match(/^Xcode (\d+)\b/m)?.[1]) >= APPLE_DEVICE_MCP_MINIMUM_XCODE;
|
|
46819
|
+
const legacyPath = environment.P4CODE_XCODEBUILDMCP_PATH?.trim();
|
|
46820
|
+
const useLegacy = environment.P4CODE_DEVICE_ADAPTER === "xcodebuildmcp";
|
|
46821
|
+
const xcode = appleAvailable && !useLegacy ? createAppleDeviceAdapter({
|
|
46822
|
+
cwd: config.stateDir,
|
|
46823
|
+
environment: hostEnvironment,
|
|
46824
|
+
fs,
|
|
46825
|
+
run,
|
|
46826
|
+
...environment.P4CODE_APPLE_MCP_WORKSPACE ? { workspacePath: environment.P4CODE_APPLE_MCP_WORKSPACE } : {}
|
|
46827
|
+
}) : platform === "darwin" && legacyPath ? createXcodeDeviceAdapter(legacyPath, config.stateDir, hostEnvironment) : void 0;
|
|
45867
46828
|
const stopAgent = Effect.suspend(() => {
|
|
46829
|
+
xcode?.stop();
|
|
45868
46830
|
const owned = agent;
|
|
45869
46831
|
agent = null;
|
|
45870
46832
|
return owned?.stop ?? Effect.void;
|
|
@@ -45903,7 +46865,8 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
|
45903
46865
|
nodePath: process.execPath,
|
|
45904
46866
|
hub: { origin: started.origin },
|
|
45905
46867
|
helpers,
|
|
45906
|
-
run
|
|
46868
|
+
run,
|
|
46869
|
+
...xcode ? { xcode } : {}
|
|
45907
46870
|
};
|
|
45908
46871
|
return ready;
|
|
45909
46872
|
}, Effect.onExit((exit) => Exit.isFailure(exit) ? stop : Effect.void));
|
|
@@ -45914,6 +46877,10 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
|
45914
46877
|
id: hostId,
|
|
45915
46878
|
kind: "local",
|
|
45916
46879
|
label: "This machine",
|
|
46880
|
+
...xcode ? { automation: {
|
|
46881
|
+
provider: appleAvailable && !useLegacy ? "apple-xcode" : "xcodebuildmcp",
|
|
46882
|
+
detail: appleAvailable && !useLegacy ? "Apple Xcode MCP. Agent and folder approval is required; P4 never grants it automatically." : "Optional XcodeBuildMCP 2.7.0 executable. No automatic installation."
|
|
46883
|
+
} } : {},
|
|
45917
46884
|
platforms: yield* Effect.all([platformAvailability("ios"), platformAvailability("android")]),
|
|
45918
46885
|
hubInstalled: yield* isDeviceHubInstalled(config.baseDir).pipe(Effect.provideContext(context)),
|
|
45919
46886
|
agentDeviceInstalled: yield* isAgentDeviceInstalled(config.baseDir).pipe(Effect.provideContext(context))
|
|
@@ -45925,8 +46892,9 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
|
45925
46892
|
return ready;
|
|
45926
46893
|
})),
|
|
45927
46894
|
ensureReady: (onPhase) => lock.withPermit(ensureHub(onPhase)),
|
|
45928
|
-
ensureAgentReady: (onPhase) => lock.withPermit(Effect.gen(function* () {
|
|
46895
|
+
ensureAgentReady: (onPhase, devicePlatform) => lock.withPermit(Effect.gen(function* () {
|
|
45929
46896
|
const host = yield* ensureHub(onPhase);
|
|
46897
|
+
if (xcode && devicePlatform === "ios") return host;
|
|
45930
46898
|
if (agent && (yield* agent.isRunning)) return {
|
|
45931
46899
|
...host,
|
|
45932
46900
|
agentDevice: agent.endpoint
|
|
@@ -45953,7 +46921,7 @@ const make$81 = Effect.fn("LocalDeviceHost.make")(function* () {
|
|
|
45953
46921
|
stop: lock.withPermit(stop)
|
|
45954
46922
|
};
|
|
45955
46923
|
});
|
|
45956
|
-
Layer.effect(DeviceHost, make$81()).pipe(Layer.provide(layer$
|
|
46924
|
+
Layer.effect(DeviceHost, make$81()).pipe(Layer.provide(layer$73));
|
|
45957
46925
|
Data.TaggedError("SshHostDiscoveryError");
|
|
45958
46926
|
var SshInvalidTargetError = class extends Data.TaggedError("SshInvalidTargetError") {};
|
|
45959
46927
|
var SshCommandError = class extends Data.TaggedError("SshCommandError") {};
|
|
@@ -46952,9 +47920,17 @@ var DeviceService = class extends Context.Service()("@p4code/cli/device/DeviceSe
|
|
|
46952
47920
|
const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input) {
|
|
46953
47921
|
const settings = yield* ServerSettingsService;
|
|
46954
47922
|
const scope = yield* Scope.Scope;
|
|
46955
|
-
const registry = yield* make$
|
|
46956
|
-
const commands = yield* make$
|
|
46957
|
-
const
|
|
47923
|
+
const registry = yield* make$83(input);
|
|
47924
|
+
const commands = yield* make$85();
|
|
47925
|
+
const adapterLeases = /* @__PURE__ */ new Map();
|
|
47926
|
+
const closeCommands = (sessions) => Effect.sync(() => {
|
|
47927
|
+
for (const session of sessions) {
|
|
47928
|
+
if (!session.leaseId) continue;
|
|
47929
|
+
adapterLeases.get(session.leaseId)?.();
|
|
47930
|
+
adapterLeases.delete(session.leaseId);
|
|
47931
|
+
}
|
|
47932
|
+
}).pipe(Effect.andThen(commands.close(sessions)));
|
|
47933
|
+
const threads = yield* make$84();
|
|
46958
47934
|
const changes = yield* Effect.acquireRelease(PubSub.sliding(STATE_BUFFER_SIZE), PubSub.shutdown);
|
|
46959
47935
|
const stateLock = yield* Semaphore.make(1);
|
|
46960
47936
|
const discoveryLock = yield* Semaphore.make(1);
|
|
@@ -46991,7 +47967,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
46991
47967
|
}));
|
|
46992
47968
|
}
|
|
46993
47969
|
const retireSessions = (ids) => Effect.gen(function* () {
|
|
46994
|
-
yield*
|
|
47970
|
+
yield* closeCommands(state.sessions.filter((session) => ids.includes(session.hostId)));
|
|
46995
47971
|
yield* update((current) => {
|
|
46996
47972
|
for (const id of ids) hostLocks.delete(id);
|
|
46997
47973
|
return {
|
|
@@ -47202,7 +48178,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47202
48178
|
return yield* withHost(value.hostId, (lease) => Effect.gen(function* () {
|
|
47203
48179
|
let found = yield* freshDevice(lease, value);
|
|
47204
48180
|
if (access === "agent") {
|
|
47205
|
-
yield* lease.host.ensureAgentReady(() => Effect.void);
|
|
48181
|
+
yield* lease.host.ensureAgentReady(() => Effect.void, value.platform);
|
|
47206
48182
|
yield* registry.commit(lease, () => void 0);
|
|
47207
48183
|
}
|
|
47208
48184
|
if (!found.device.booted && value.boot !== false) {
|
|
@@ -47241,7 +48217,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47241
48217
|
openedAt,
|
|
47242
48218
|
leaseId: NodeCrypto.randomUUID()
|
|
47243
48219
|
};
|
|
47244
|
-
yield*
|
|
48220
|
+
yield* closeCommands(sessionsToClose(state.sessions, session));
|
|
47245
48221
|
yield* update((current) => ({
|
|
47246
48222
|
...current,
|
|
47247
48223
|
sessions: [...current.sessions.filter((item) => !(item.threadId === session.threadId && item.hostId === session.hostId && item.deviceId === session.deviceId)), session]
|
|
@@ -47252,7 +48228,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47252
48228
|
const shutdownWithin = Effect.fn("DeviceService.shutdownWithin")(function* (lease, value) {
|
|
47253
48229
|
const { ready, device } = yield* freshDevice(lease, value);
|
|
47254
48230
|
yield* input.actions.shutdown(ready, device);
|
|
47255
|
-
yield*
|
|
48231
|
+
yield* closeCommands(state.sessions.filter((session) => session.hostId === value.hostId && session.deviceId === value.deviceId));
|
|
47256
48232
|
yield* update((current) => ({
|
|
47257
48233
|
...current,
|
|
47258
48234
|
devices: current.devices.map((item) => item.hostId === value.hostId && item.id === value.deviceId ? {
|
|
@@ -47276,7 +48252,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47276
48252
|
platform: session.platform
|
|
47277
48253
|
});
|
|
47278
48254
|
else {
|
|
47279
|
-
yield*
|
|
48255
|
+
yield* closeCommands(sessionsToClose(state.sessions, value));
|
|
47280
48256
|
yield* update((current) => {
|
|
47281
48257
|
const closing = sessionsToClose(current.sessions, value);
|
|
47282
48258
|
return {
|
|
@@ -47319,11 +48295,16 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47319
48295
|
});
|
|
47320
48296
|
const validate = registry.isCurrent(lease).pipe(Effect.map((current) => current && state.sessions.includes(session)));
|
|
47321
48297
|
return yield* commands.run(session, validate, Effect.gen(function* () {
|
|
47322
|
-
const ready = yield* lease.host.ensureAgentReady(() => Effect.void);
|
|
48298
|
+
const ready = yield* lease.host.ensureAgentReady(() => Effect.void, session.platform);
|
|
47323
48299
|
if (!(yield* validate)) return yield* new DeviceHostUnavailableError({
|
|
47324
48300
|
hostId: target.hostId,
|
|
47325
48301
|
reason: "Device session or agent authorization changed."
|
|
47326
48302
|
});
|
|
48303
|
+
if (ready.xcode && session.leaseId) {
|
|
48304
|
+
const adapter = ready.xcode;
|
|
48305
|
+
const leaseId = session.leaseId;
|
|
48306
|
+
adapterLeases.set(leaseId, () => adapter.closeSession(leaseId));
|
|
48307
|
+
}
|
|
47327
48308
|
return yield* execute(ready, session);
|
|
47328
48309
|
}));
|
|
47329
48310
|
})).pipe(Effect.mapError((error) => isDeviceHostError(error) || isDeviceHostTimeoutError(error) ? new DeviceHostUnavailableError({
|
|
@@ -47337,7 +48318,7 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47337
48318
|
agentList: listForAccess("agent"),
|
|
47338
48319
|
configure,
|
|
47339
48320
|
shutdown,
|
|
47340
|
-
retireThread: (threadId) => threads.retire(threadId).pipe(Effect.ensuring(Effect.suspend(() =>
|
|
48321
|
+
retireThread: (threadId) => threads.retire(threadId).pipe(Effect.ensuring(Effect.suspend(() => closeCommands(state.sessions.filter((session) => session.threadId === threadId))).pipe(Effect.ensuring(update((current) => ({
|
|
47341
48322
|
...current,
|
|
47342
48323
|
sessions: current.sessions.filter((session) => session.threadId !== threadId),
|
|
47343
48324
|
bootingDevices: (current.bootingDevices ?? []).filter((device) => device.threadId !== threadId)
|
|
@@ -47345,7 +48326,10 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47345
48326
|
restoreThread: threads.restore,
|
|
47346
48327
|
withAgentDevice: (target, execute) => threads.run(target.threadId, withAgentDevice(target, execute)),
|
|
47347
48328
|
withManualDevice: (target, execute) => threads.run(target.threadId, withManualDevice(target, execute)),
|
|
47348
|
-
withAgentCommand: (target, execute) => threads.run(target.threadId, withAgentDevice(target, (ready, session) => execute(ready.agentDevice, session)
|
|
48329
|
+
withAgentCommand: (target, execute) => threads.run(target.threadId, withAgentDevice(target, (ready, session) => ready.agentDevice ? execute(ready.agentDevice, session) : Effect.fail(new DeviceHostUnavailableError({
|
|
48330
|
+
hostId: target.hostId,
|
|
48331
|
+
reason: "This host uses semantic device control. Use cua.getDevice() and element refs."
|
|
48332
|
+
})))),
|
|
47349
48333
|
open: (value) => threads.run(value.threadId, openWithAccess(value, "manual")),
|
|
47350
48334
|
agentOpen: (value) => threads.run(value.threadId, openWithAccess(value, "agent")),
|
|
47351
48335
|
close: (value) => closeWithAccess(value, "manual"),
|
|
@@ -47358,15 +48342,15 @@ const makeWithHosts = Effect.fn("DeviceService.makeWithHosts")(function* (input)
|
|
|
47358
48342
|
};
|
|
47359
48343
|
});
|
|
47360
48344
|
const make$79 = Effect.gen(function* () {
|
|
47361
|
-
const discover = yield* make$
|
|
47362
|
-
const actions = yield* make$
|
|
48345
|
+
const discover = yield* make$87();
|
|
48346
|
+
const actions = yield* make$86();
|
|
47363
48347
|
return yield* makeWithHosts({
|
|
47364
48348
|
local: make$81(),
|
|
47365
48349
|
ssh: make$80,
|
|
47366
48350
|
discover,
|
|
47367
48351
|
actions
|
|
47368
48352
|
});
|
|
47369
|
-
}).pipe(Effect.provide(layer$
|
|
48353
|
+
}).pipe(Effect.provide(layer$73));
|
|
47370
48354
|
const layer$70 = Layer.effect(DeviceService, make$79);
|
|
47371
48355
|
//#endregion
|
|
47372
48356
|
//#region src/serverRuntimeStartup.ts
|
|
@@ -47979,7 +48963,7 @@ const projectCommandUuid = Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.
|
|
|
47979
48963
|
operation: "generateProjectCommandId",
|
|
47980
48964
|
cause
|
|
47981
48965
|
})));
|
|
47982
|
-
const ProjectCliRuntimeLive = Layer.mergeAll(layer$68, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$
|
|
48966
|
+
const ProjectCliRuntimeLive = Layer.mergeAll(layer$68, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$81), Layer.provideMerge(layerConfig)));
|
|
47983
48967
|
const PROJECT_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(1);
|
|
47984
48968
|
const withProjectCliSessionToken = (environmentAuth, run) => Effect.acquireUseRelease(environmentAuth.issueSession({
|
|
47985
48969
|
scopes: AuthAdministrativeScopes,
|
|
@@ -48070,7 +49054,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
48070
49054
|
});
|
|
48071
49055
|
yield* Console.log(output);
|
|
48072
49056
|
}));
|
|
48073
|
-
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$
|
|
49057
|
+
const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$118(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
|
|
48074
49058
|
return yield* Effect.gen(function* () {
|
|
48075
49059
|
const snapshot = yield* getOfflineSnapshot();
|
|
48076
49060
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
@@ -48081,7 +49065,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
|
|
|
48081
49065
|
});
|
|
48082
49066
|
yield* Console.log(output);
|
|
48083
49067
|
}).pipe(Effect.provide(offlineRuntimeLayer));
|
|
48084
|
-
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$68).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$
|
|
49068
|
+
}).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$68).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$118(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
|
|
48085
49069
|
});
|
|
48086
49070
|
const projectAddCommand = Command.make("add", {
|
|
48087
49071
|
...projectLocationFlags,
|
|
@@ -53298,80 +54282,6 @@ const make$75 = Effect.fn("DeviceCommandProxy.make")(function* () {
|
|
|
53298
54282
|
var DeviceCommandProxy = class extends Context.Service()("@p4code/cli/device/DeviceCommandProxy") {};
|
|
53299
54283
|
const layer$67 = Layer.effect(DeviceCommandProxy, make$75().pipe(Effect.map((execute) => ({ execute }))));
|
|
53300
54284
|
//#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
54285
|
//#region src/device/DeviceHubRoute.ts
|
|
53376
54286
|
const DEVICE_HUB_PROXY_PREFIX = "/api/device-hub";
|
|
53377
54287
|
const MAX_ROUTE_LENGTH = 16 * 1024;
|
|
@@ -53574,12 +54484,12 @@ const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* (fusion
|
|
|
53574
54484
|
const isDeviceToolUnavailableError = Schema$1.is(DeviceToolUnavailableError);
|
|
53575
54485
|
const isDeviceActionUnavailableError = Schema$1.is(DeviceActionUnavailableError);
|
|
53576
54486
|
/** Internal bridge; tool payloads never choose thread identity or daemon credentials. */
|
|
53577
|
-
const withDeviceInvocation = (execute) => Effect.gen(function* () {
|
|
54487
|
+
const withDeviceInvocation = (execute, capability = "devices") => Effect.gen(function* () {
|
|
53578
54488
|
const invocation = yield* McpInvocationContext;
|
|
53579
54489
|
const service = yield* DeviceService;
|
|
53580
54490
|
const lifetime = invocation.authorizationLifetime;
|
|
53581
54491
|
const denied = () => new DeviceToolUnavailableError({ reason: "Device command unavailable or authorization changed." });
|
|
53582
|
-
if (!invocation.capabilities.has(
|
|
54492
|
+
if (!invocation.capabilities.has(capability) || !lifetime?.revocation || lifetime.revoked) return yield* denied();
|
|
53583
54493
|
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
54494
|
return yield* Effect.raceFirst(work, Deferred.await(lifetime.revocation).pipe(Effect.andThen(Effect.fail(denied()))));
|
|
53585
54495
|
});
|
|
@@ -53594,6 +54504,7 @@ const MAX_AX_BYTES = 512 * 1024;
|
|
|
53594
54504
|
const AX_TIMEOUT_MS = 1e4;
|
|
53595
54505
|
const MAX_AX_EXTENT = 32768;
|
|
53596
54506
|
const MIN_AX_EXTENT = 2;
|
|
54507
|
+
const isToolUnavailable = Schema$1.is(DeviceToolUnavailableError);
|
|
53597
54508
|
const AxFrames = Schema$1.Array(Schema$1.Struct({ frame: Schema$1.Struct({
|
|
53598
54509
|
x: Schema$1.Number,
|
|
53599
54510
|
y: Schema$1.Number,
|
|
@@ -53633,6 +54544,7 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
53633
54544
|
const state = yield* service.agentList;
|
|
53634
54545
|
const device = state.devices.find((device) => device.hostId === input.hostId && device.id === input.deviceId && device.platform === input.platform);
|
|
53635
54546
|
if (!device) return yield* stale();
|
|
54547
|
+
if (device.physical) return yield* new DeviceToolUnavailableError({ reason: "Physical-device UI control is not supported by this adapter. Pairing, trust, Developer Mode and signing must be configured separately; use supported device-management workflows." });
|
|
53636
54548
|
const session = yield* service.agentOpen({
|
|
53637
54549
|
threadId,
|
|
53638
54550
|
hostId: input.hostId,
|
|
@@ -53670,8 +54582,16 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
53670
54582
|
deviceId: target.deviceId
|
|
53671
54583
|
}, (ready, session) => Effect.gen(function* () {
|
|
53672
54584
|
if (session.leaseId !== input.leaseId) return yield* stale();
|
|
54585
|
+
if (input.method === "recording") {
|
|
54586
|
+
if (!ready.xcode || session.platform !== "ios") return yield* new DeviceToolUnavailableError({ reason: "Recording is unavailable on this device adapter." });
|
|
54587
|
+
return yield* ready.xcode.recording(session, input.action).pipe(Effect.mapError((error) => new DeviceToolUnavailableError({ reason: String(error.cause) })));
|
|
54588
|
+
}
|
|
54589
|
+
if (input.method === "semantic") {
|
|
54590
|
+
if (!ready.xcode || session.platform !== "ios") return yield* new DeviceToolUnavailableError({ reason: "Semantic device actions require a supported local Xcode adapter. Use the capabilities returned by getAXState()." });
|
|
54591
|
+
return yield* ready.xcode.action(session, input.action).pipe(Effect.mapError((error) => new DeviceToolUnavailableError({ reason: String(error.cause) })));
|
|
54592
|
+
}
|
|
53673
54593
|
if (input.method === "screenshot") {
|
|
53674
|
-
const capture = yield* screenshots.capture(ready, session);
|
|
54594
|
+
const capture = yield* ready.xcode && session.platform === "ios" ? ready.xcode.screenshot(session).pipe(Effect.mapError((error) => new DeviceToolUnavailableError({ reason: String(error.cause) }))) : screenshots.capture(ready, session);
|
|
53675
54595
|
return {
|
|
53676
54596
|
mimeType: "image/png",
|
|
53677
54597
|
data: capture.png.toString("base64"),
|
|
@@ -53679,6 +54599,7 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
53679
54599
|
height: capture.height
|
|
53680
54600
|
};
|
|
53681
54601
|
}
|
|
54602
|
+
if (ready.xcode && session.platform === "ios") return yield* ready.xcode.state(session, input.sinceScreenHash).pipe(Effect.mapError((error) => new DeviceToolUnavailableError({ reason: String(error.cause) })));
|
|
53682
54603
|
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
54604
|
const route = resolveDeviceHubRoute({
|
|
53684
54605
|
target: {
|
|
@@ -53706,12 +54627,13 @@ const makeComputerUseDevices = Effect.fn("ComputerUseDevices.make")(function* ()
|
|
|
53706
54627
|
leaseId: session.leaseId,
|
|
53707
54628
|
accessibility
|
|
53708
54629
|
};
|
|
53709
|
-
}).pipe(Effect.scoped, Effect.
|
|
53710
|
-
|
|
53711
|
-
|
|
53712
|
-
|
|
53713
|
-
|
|
53714
|
-
|
|
54630
|
+
}).pipe(Effect.scoped, Effect.timeoutOrElse({
|
|
54631
|
+
duration: AX_TIMEOUT_MS,
|
|
54632
|
+
orElse: () => Effect.gen(function* () {
|
|
54633
|
+
return yield* new DeviceToolUnavailableError({ reason: ready.xcode && "diagnose" in ready.xcode ? yield* ready.xcode.diagnose : "Device state request timed out. Check device support before selecting the device again." });
|
|
54634
|
+
})
|
|
54635
|
+
}), Effect.mapError((error) => isToolUnavailable(error) ? error : new DeviceToolUnavailableError({ reason: error instanceof Error ? error.message : String(error) }))));
|
|
54636
|
+
}), "computer-use").pipe(Effect.provideService(McpInvocationContext, scope), Effect.provideService(DeviceService, devices), Effect.mapError((error) => new ComputerUseError({
|
|
53715
54637
|
reason: "unavailable",
|
|
53716
54638
|
detail: error.message
|
|
53717
54639
|
})));
|
|
@@ -53737,7 +54659,7 @@ const hostSession = (scope) => ({
|
|
|
53737
54659
|
providerSessionId: scope.providerSessionId
|
|
53738
54660
|
});
|
|
53739
54661
|
var ComputerUseBroker = class extends Context.Service()("@p4code/cli/mcp/ComputerUseBroker") {};
|
|
53740
|
-
const layer$
|
|
54662
|
+
const layer$66 = Layer.effect(ComputerUseBroker, Effect.gen(function* () {
|
|
53741
54663
|
const serviceScope = yield* Scope.Scope;
|
|
53742
54664
|
const crypto = yield* Crypto.Crypto;
|
|
53743
54665
|
const environment = yield* ServerEnvironment;
|
|
@@ -54328,7 +55250,7 @@ const renew = HttpRouter.add("POST", "/internal/computer-use/renew", Effect.gen(
|
|
|
54328
55250
|
if (binding.trust) yield* (yield* RemoteComputerUseBindings).touch(bearer(request));
|
|
54329
55251
|
return HttpServerResponse.empty({ status: 204 });
|
|
54330
55252
|
}).pipe(Effect.catch(failure$1)));
|
|
54331
|
-
const layer$
|
|
55253
|
+
const layer$65 = Layer.mergeAll(exchange, hubForward, hubExchange, connect, respond, device, report, environment, renew).pipe(Layer.provide(remoteComputerUseBindingsLayer));
|
|
54332
55254
|
//#endregion
|
|
54333
55255
|
//#region src/device/DeviceHubSocketProtocol.ts
|
|
54334
55256
|
const MAX_DEVICE_INPUT_BYTES = 8 * 1024;
|
|
@@ -55706,7 +56628,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
|
|
|
55706
56628
|
filePath: error.filePath,
|
|
55707
56629
|
errorTag: error._tag
|
|
55708
56630
|
}));
|
|
55709
|
-
const make$
|
|
56631
|
+
const make$74 = Effect.gen(function* () {
|
|
55710
56632
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
55711
56633
|
const path = yield* Path$1.Path;
|
|
55712
56634
|
const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
|
|
@@ -55727,7 +56649,7 @@ const make$73 = Effect.gen(function* () {
|
|
|
55727
56649
|
});
|
|
55728
56650
|
return P4ProjectFileLoader.of({ load });
|
|
55729
56651
|
});
|
|
55730
|
-
const layer$
|
|
56652
|
+
const layer$64 = Layer.effect(P4ProjectFileLoader, make$74);
|
|
55731
56653
|
//#endregion
|
|
55732
56654
|
//#region src/project/ProjectFaviconResolver.ts
|
|
55733
56655
|
/**
|
|
@@ -55802,7 +56724,7 @@ function extractIconHref(source) {
|
|
|
55802
56724
|
return null;
|
|
55803
56725
|
}
|
|
55804
56726
|
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) }));
|
|
55805
|
-
const make$
|
|
56727
|
+
const make$73 = Effect.gen(function* () {
|
|
55806
56728
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
55807
56729
|
const path = yield* Path$1.Path;
|
|
55808
56730
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -55871,7 +56793,7 @@ const make$72 = Effect.gen(function* () {
|
|
|
55871
56793
|
});
|
|
55872
56794
|
return ProjectFaviconResolver.of({ resolvePath });
|
|
55873
56795
|
});
|
|
55874
|
-
const layer$
|
|
56796
|
+
const layer$63 = Layer.effect(ProjectFaviconResolver, make$73);
|
|
55875
56797
|
//#endregion
|
|
55876
56798
|
//#region src/assets/AssetAccess.ts
|
|
55877
56799
|
const ASSET_ROUTE_PREFIX = "/api/assets";
|
|
@@ -56282,10 +57204,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
56282
57204
|
//#endregion
|
|
56283
57205
|
//#region src/observability/BrowserTraceCollector.ts
|
|
56284
57206
|
var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
|
|
56285
|
-
const make$
|
|
57207
|
+
const make$72 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
|
|
56286
57208
|
for (const record of records) sink.push(record);
|
|
56287
57209
|
}) });
|
|
56288
|
-
const layer$
|
|
57210
|
+
const layer$62 = (sink) => Layer.succeed(BrowserTraceCollector, make$72(sink));
|
|
56289
57211
|
//#endregion
|
|
56290
57212
|
//#region src/auth/http.ts
|
|
56291
57213
|
const CREDENTIAL_RESPONSE_HEADERS = {
|
|
@@ -57427,7 +58349,7 @@ const defaultCancelTimeout = Duration.seconds(15);
|
|
|
57427
58349
|
const defaultSessionLoadTimeout = Duration.seconds(90);
|
|
57428
58350
|
const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
|
|
57429
58351
|
var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
|
|
57430
|
-
const make$
|
|
58352
|
+
const make$71 = (options) => Effect.gen(function* () {
|
|
57431
58353
|
const crypto = yield* Crypto.Crypto;
|
|
57432
58354
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
57433
58355
|
const runtimeScope = yield* Scope.Scope;
|
|
@@ -57831,7 +58753,7 @@ const make$70 = (options) => Effect.gen(function* () {
|
|
|
57831
58753
|
notify: acp.raw.notify
|
|
57832
58754
|
};
|
|
57833
58755
|
});
|
|
57834
|
-
const layer$
|
|
58756
|
+
const layer$61 = (options) => Layer.effect(AcpSessionRuntime, make$71(options));
|
|
57835
58757
|
function sessionConfigOptionsFromSetup(response) {
|
|
57836
58758
|
return response?.configOptions ?? [];
|
|
57837
58759
|
}
|
|
@@ -58225,7 +59147,7 @@ const buildAntigravityPrompt = Effect.fn("buildAntigravityPrompt")(function* (in
|
|
|
58225
59147
|
});
|
|
58226
59148
|
/** Normal launches reject browser login; only the auth flow supplies `onAuthorizationUrl`. */
|
|
58227
59149
|
const makeAntigravityAcpRuntime = Effect.fn("makeAntigravityAcpRuntime")(function* (input) {
|
|
58228
|
-
const context = yield* Layer.build(layer$
|
|
59150
|
+
const context = yield* Layer.build(layer$61({
|
|
58229
59151
|
...input,
|
|
58230
59152
|
authMethodId: input.authMethod ?? "oauth-personal",
|
|
58231
59153
|
resumeMethod: "resume",
|
|
@@ -62202,7 +63124,7 @@ const BundledOnlyModelManifest = {
|
|
|
62202
63124
|
refreshInBackground: Effect.void
|
|
62203
63125
|
};
|
|
62204
63126
|
Layer.succeed(ModelManifest, BundledOnlyModelManifest);
|
|
62205
|
-
const make$
|
|
63127
|
+
const make$70 = Effect.gen(function* () {
|
|
62206
63128
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
62207
63129
|
const path = yield* Path$1.Path;
|
|
62208
63130
|
const config = yield* ServerConfig$1;
|
|
@@ -62247,7 +63169,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
62247
63169
|
refreshInBackground: Effect.forkIn(guardedRefresh, serviceScope).pipe(Effect.asVoid)
|
|
62248
63170
|
});
|
|
62249
63171
|
});
|
|
62250
|
-
const layer$
|
|
63172
|
+
const layer$60 = Layer.effect(ModelManifest, make$70);
|
|
62251
63173
|
//#endregion
|
|
62252
63174
|
//#region src/provider/ProviderDriver.ts
|
|
62253
63175
|
function defaultProviderContinuationIdentity(input) {
|
|
@@ -62507,11 +63429,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
|
|
|
62507
63429
|
detail: "This provider does not report account usage."
|
|
62508
63430
|
}))))
|
|
62509
63431
|
});
|
|
62510
|
-
const make$
|
|
63432
|
+
const make$69 = Effect.gen(function* () {
|
|
62511
63433
|
const registry = yield* ProviderInstanceRegistry;
|
|
62512
63434
|
return makeTextGenerationFromRegistry(registry);
|
|
62513
63435
|
});
|
|
62514
|
-
const layer$
|
|
63436
|
+
const layer$59 = Layer.effect(TextGeneration, make$69);
|
|
62515
63437
|
//#endregion
|
|
62516
63438
|
//#region src/provider/Layers/claudeUsageLimits.ts
|
|
62517
63439
|
const SESSION_MINS$1 = 300;
|
|
@@ -64186,7 +65108,7 @@ function formatAskUserQuestionAnswers(answers) {
|
|
|
64186
65108
|
* written as if the setting applied only to user-facing answers.
|
|
64187
65109
|
*/
|
|
64188
65110
|
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}`;
|
|
65111
|
+
const FUSION_BUILDER_INSTRUCTIONS = `You are Fusion Builder in an already-created native server pair. Server owns pairing and coordination. Follow the current turn's [fusion-review-policy] block when present; it overrides the phase-boundary scheduling rules below. 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}`;
|
|
64190
65112
|
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:
|
|
64191
65113
|
## Recommendation
|
|
64192
65114
|
State the decision or correction in one sentence. For a phase review, say whether the phase is approved or needs changes.
|
|
@@ -64194,7 +65116,7 @@ State the decision or correction in one sentence. For a phase review, say whethe
|
|
|
64194
65116
|
Give concise evidence, relevant file/line references, and any unresolved risk. Distinguish observed facts from assumptions; do not claim checks you did not run.
|
|
64195
65117
|
## Next step
|
|
64196
65118
|
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.`;
|
|
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}`;
|
|
65119
|
+
const FUSION_WATCHER_INSTRUCTIONS = `You are Fusion Supervisor (watcher) in an already-created native server pair. Follow the current turn's [fusion-review-policy] block when present; it overrides phase scheduling. 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}`;
|
|
64198
65120
|
/**
|
|
64199
65121
|
* The one-line stand-in for the full block on a message whose session already
|
|
64200
65122
|
* carries the role instructions.
|
|
@@ -64214,6 +65136,13 @@ function fusionRoleInstructionsFor(role) {
|
|
|
64214
65136
|
function fusionRoleReferenceLineFor(role) {
|
|
64215
65137
|
return role === "implementer" ? FUSION_BUILDER_REFERENCE_LINE : FUSION_WATCHER_REFERENCE_LINE;
|
|
64216
65138
|
}
|
|
65139
|
+
function fusionReviewPolicyInstructions(experiment) {
|
|
65140
|
+
if (!experiment) return "";
|
|
65141
|
+
const { policy } = experiment;
|
|
65142
|
+
return `[fusion-review-policy] Authoritative policy for this pair, overriding phase-boundary rules in session instructions: ${policy.mode}.
|
|
65143
|
+
${policy.mode === "risk-and-final" ? "Builder: maintain your phase list, but continue across routine phase boundaries within the same turn. End only for a concrete unresolved judgment request, an external blocker, or final whole-task review after verification. Do not stop merely because one phase finished. Supervisor: after resolving a judgment request, direct the builder to continue through remaining routine phases and final verification; do not require another intermediate phase stop." : "Builder: retain one phase per turn. Supervisor: retain phase reviews."}
|
|
65144
|
+
At most ${policy.maxAutomaticReviews} automatic reviews and ${policy.maxCorrectionRounds} advice turns after review per human instruction. Initial direction is free. Current usage: ${experiment.automaticReviews} reviews, ${experiment.correctionRounds} correction rounds. Gate review wakes also consume reviews. Budget exhaustion pauses unresolved work; it never approves it. Human instruction to either thread resets the budget. Never send acknowledgment-only advice.`;
|
|
65145
|
+
}
|
|
64217
65146
|
//#endregion
|
|
64218
65147
|
//#region src/provider/GuardrailPrompts.ts
|
|
64219
65148
|
/** Fresh-evidence gate adapted from superpowers' verification skill. */
|
|
@@ -65658,6 +66587,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
65658
66587
|
context.inFlightTools.delete(index);
|
|
65659
66588
|
}
|
|
65660
66589
|
context.inFlightTools.clear();
|
|
66590
|
+
for (const toolUseId of context.subagentModels.keys()) if (!context.subagentTasks.has(toolUseId)) context.subagentModels.delete(toolUseId);
|
|
65661
66591
|
for (const block of turnState.assistantTextBlockOrder) yield* completeAssistantTextBlock(context, block, {
|
|
65662
66592
|
force: true,
|
|
65663
66593
|
rawMethod: "claude/result",
|
|
@@ -65826,9 +66756,31 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
65826
66756
|
discard: true
|
|
65827
66757
|
});
|
|
65828
66758
|
});
|
|
66759
|
+
const recordSubagentModel = Effect.fn("recordSubagentModel")(function* (context, toolUseId, model) {
|
|
66760
|
+
if (!toolUseId || !model || context.subagentModels.get(toolUseId) === model) return;
|
|
66761
|
+
const task = context.subagentTasks.get(toolUseId);
|
|
66762
|
+
if (!task && !Array.from(context.inFlightTools.values()).some((tool) => tool.itemId === toolUseId)) return;
|
|
66763
|
+
context.subagentModels.set(toolUseId, model);
|
|
66764
|
+
if (!task) return;
|
|
66765
|
+
yield* offerRuntimeEvent({
|
|
66766
|
+
...yield* makeEventStamp(),
|
|
66767
|
+
type: "task.progress",
|
|
66768
|
+
provider: PROVIDER$6,
|
|
66769
|
+
threadId: context.session.threadId,
|
|
66770
|
+
...context.turnState ? { turnId: asCanonicalTurnId(context.turnState.turnId) } : {},
|
|
66771
|
+
payload: {
|
|
66772
|
+
taskId: RuntimeTaskId.make(task.taskId),
|
|
66773
|
+
description: task.description,
|
|
66774
|
+
toolUseId,
|
|
66775
|
+
...task.subagentType ? { subagentType: task.subagentType } : {},
|
|
66776
|
+
model
|
|
66777
|
+
}
|
|
66778
|
+
});
|
|
66779
|
+
});
|
|
65829
66780
|
const handleStreamEvent = Effect.fn("handleStreamEvent")(function* (context, message) {
|
|
65830
66781
|
if (message.type !== "stream_event") return;
|
|
65831
66782
|
const { event } = message;
|
|
66783
|
+
if (event.type === "message_start") yield* recordSubagentModel(context, message.parent_tool_use_id, event.message.model);
|
|
65832
66784
|
if (event.type === "message_delta") {
|
|
65833
66785
|
if (message.parent_tool_use_id !== null && message.parent_tool_use_id !== void 0) return;
|
|
65834
66786
|
const snapshot = normalizeClaudeActiveTokenUsage(event.usage, context.lastKnownContextWindow, context.lastKnownTotalProcessedTokens);
|
|
@@ -66149,10 +67101,12 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
66149
67101
|
rawPayload: message
|
|
66150
67102
|
});
|
|
66151
67103
|
context.inFlightTools.delete(index);
|
|
67104
|
+
if (!context.subagentTasks.has(tool.itemId)) context.subagentModels.delete(tool.itemId);
|
|
66152
67105
|
}
|
|
66153
67106
|
});
|
|
66154
67107
|
const handleAssistantMessage = Effect.fn("handleAssistantMessage")(function* (context, message) {
|
|
66155
67108
|
if (message.type !== "assistant") return;
|
|
67109
|
+
yield* recordSubagentModel(context, message.parent_tool_use_id, message.message.model);
|
|
66156
67110
|
if (!context.turnState) {
|
|
66157
67111
|
const turnId = TurnId.make(yield* randomUUIDv4);
|
|
66158
67112
|
const startedAt = yield* nowIso;
|
|
@@ -66259,6 +67213,7 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
66259
67213
|
}
|
|
66260
67214
|
switch (message.subtype) {
|
|
66261
67215
|
case "init":
|
|
67216
|
+
context.currentApiModelId = message.model || context.currentApiModelId;
|
|
66262
67217
|
yield* offerRuntimeEvent({
|
|
66263
67218
|
...base,
|
|
66264
67219
|
type: "session.configured",
|
|
@@ -66329,7 +67284,12 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
66329
67284
|
return;
|
|
66330
67285
|
case "task_started": {
|
|
66331
67286
|
const requestedModel = readString((message.tool_use_id ? Array.from(context.inFlightTools.values()).find((tool) => tool.itemId === message.tool_use_id) : void 0)?.input.model);
|
|
66332
|
-
const model = requestedModel === "inherit" ? context.currentApiModelId : requestedModel;
|
|
67287
|
+
const model = (message.tool_use_id ? context.subagentModels.get(message.tool_use_id) : void 0) ?? (requestedModel === "inherit" ? context.currentApiModelId : requestedModel);
|
|
67288
|
+
if (message.tool_use_id) context.subagentTasks.set(message.tool_use_id, {
|
|
67289
|
+
taskId: message.task_id,
|
|
67290
|
+
description: message.description,
|
|
67291
|
+
...message.subagent_type ? { subagentType: message.subagent_type } : {}
|
|
67292
|
+
});
|
|
66333
67293
|
yield* offerRuntimeEvent({
|
|
66334
67294
|
...base,
|
|
66335
67295
|
type: "task.started",
|
|
@@ -66380,6 +67340,11 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
66380
67340
|
...message.tool_use_id ? { toolUseId: message.tool_use_id } : {}
|
|
66381
67341
|
}
|
|
66382
67342
|
});
|
|
67343
|
+
for (const [toolUseId, task] of context.subagentTasks) if (toolUseId === message.tool_use_id || task.taskId === message.task_id) {
|
|
67344
|
+
context.subagentTasks.delete(toolUseId);
|
|
67345
|
+
context.subagentModels.delete(toolUseId);
|
|
67346
|
+
}
|
|
67347
|
+
if (message.tool_use_id) context.subagentModels.delete(message.tool_use_id);
|
|
66383
67348
|
return;
|
|
66384
67349
|
case "files_persisted":
|
|
66385
67350
|
yield* offerRuntimeEvent({
|
|
@@ -67080,6 +68045,8 @@ const makeClaudeAdapter = Effect.fn("makeClaudeAdapter")(function* (claudeSettin
|
|
|
67080
68045
|
turns: [],
|
|
67081
68046
|
inFlightTools,
|
|
67082
68047
|
claudeTasks,
|
|
68048
|
+
subagentTasks: /* @__PURE__ */ new Map(),
|
|
68049
|
+
subagentModels: /* @__PURE__ */ new Map(),
|
|
67083
68050
|
turnState: void 0,
|
|
67084
68051
|
pendingTurnRequest: void 0,
|
|
67085
68052
|
steeredMessages: /* @__PURE__ */ new Map(),
|
|
@@ -85454,7 +86421,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
|
|
|
85454
86421
|
//#endregion
|
|
85455
86422
|
//#region ../../packages/effect-codex-app-server/src/client.ts
|
|
85456
86423
|
var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
|
|
85457
|
-
const make$
|
|
86424
|
+
const make$68 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
|
|
85458
86425
|
const requestHandlers = /* @__PURE__ */ new Map();
|
|
85459
86426
|
const notificationHandlers = /* @__PURE__ */ new Map();
|
|
85460
86427
|
let unknownRequestHandler;
|
|
@@ -85521,7 +86488,7 @@ const make$67 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(f
|
|
|
85521
86488
|
const layerChildProcess = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
|
|
85522
86489
|
const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
|
|
85523
86490
|
yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
|
|
85524
|
-
return yield* make$
|
|
86491
|
+
return yield* make$68(makeChildStdio(handle), options, makeTerminationError(handle));
|
|
85525
86492
|
});
|
|
85526
86493
|
const resolveCodexLaunchArgs = (launchArgs, environment = process.env) => environment["P4CODE_CODEX_LAUNCH_ARGS"]?.trim() || launchArgs?.trim() || "";
|
|
85527
86494
|
const codexLaunchArgv = (launchArgs) => tokenizeCliArgs(launchArgs);
|
|
@@ -89365,7 +90332,7 @@ function buildCursorDiscoveredModelsFromAvailableModelsResponse(response) {
|
|
|
89365
90332
|
}
|
|
89366
90333
|
const makeCursorAcpProbeRuntime = (cursorSettings, environment) => Effect.gen(function* () {
|
|
89367
90334
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
89368
|
-
const acpContext = yield* Layer.build(layer$
|
|
90335
|
+
const acpContext = yield* Layer.build(layer$61({
|
|
89369
90336
|
spawn: {
|
|
89370
90337
|
command: cursorSettings.binaryPath,
|
|
89371
90338
|
args: [...cursorSettings.apiEndpoint ? ["-e", cursorSettings.apiEndpoint] : [], "acp"],
|
|
@@ -89815,7 +90782,7 @@ function buildCursorAcpSpawnInput(cursorSettings, cwd, environment) {
|
|
|
89815
90782
|
};
|
|
89816
90783
|
}
|
|
89817
90784
|
const makeCursorAcpRuntime = (input) => Effect.gen(function* () {
|
|
89818
|
-
const acpContext = yield* Layer.build(layer$
|
|
90785
|
+
const acpContext = yield* Layer.build(layer$61({
|
|
89819
90786
|
...input,
|
|
89820
90787
|
spawn: buildCursorAcpSpawnInput(input.cursorSettings, input.cwd, input.environment),
|
|
89821
90788
|
authMethodId: "cursor_login",
|
|
@@ -91008,7 +91975,7 @@ function resolveGrokAuthMethodId(environment) {
|
|
|
91008
91975
|
return environment?.[GROK_API_KEY_ENV]?.trim() ? GROK_AUTH_METHOD_API_KEY : GROK_AUTH_METHOD_CACHED_TOKEN;
|
|
91009
91976
|
}
|
|
91010
91977
|
const makeGrokAcpRuntime = (input) => Effect.gen(function* () {
|
|
91011
|
-
const acpContext = yield* Layer.build(layer$
|
|
91978
|
+
const acpContext = yield* Layer.build(layer$61({
|
|
91012
91979
|
...input,
|
|
91013
91980
|
spawn: buildGrokAcpSpawnInput(input.grokSettings, input.cwd, input.environment),
|
|
91014
91981
|
authMethodId: resolveGrokAuthMethodId(input.environment)
|
|
@@ -94467,7 +95434,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
|
|
|
94467
95434
|
};
|
|
94468
95435
|
});
|
|
94469
95436
|
var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
|
|
94470
|
-
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$
|
|
95437
|
+
const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$119));
|
|
94471
95438
|
//#endregion
|
|
94472
95439
|
//#region src/textGeneration/OpenCodeTextGeneration.ts
|
|
94473
95440
|
const OPENCODE_TEXT_GENERATION_IDLE_TTL = "30 seconds";
|
|
@@ -97057,8 +98024,8 @@ const makeWithReader = (api) => Effect.gen(function* () {
|
|
|
97057
98024
|
}))
|
|
97058
98025
|
};
|
|
97059
98026
|
});
|
|
97060
|
-
const make$
|
|
97061
|
-
const layer$
|
|
98027
|
+
const make$67 = makeCliproxyApi.pipe(Effect.flatMap(makeWithReader));
|
|
98028
|
+
const layer$58 = Layer.effect(UsageLimitSources, make$67);
|
|
97062
98029
|
//#endregion
|
|
97063
98030
|
//#region src/resourceTelemetry/HostResources.ts
|
|
97064
98031
|
const CPU_SAMPLE_INTERVAL = "200 millis";
|
|
@@ -97093,7 +98060,7 @@ function darwinAvailableMemory(output) {
|
|
|
97093
98060
|
const available = (Number(free) + Number(inactive) + Number(speculative)) * Number(pageSize);
|
|
97094
98061
|
return Number.isSafeInteger(available) && Number(pageSize) > 0 ? available : null;
|
|
97095
98062
|
}
|
|
97096
|
-
const make$
|
|
98063
|
+
const make$66 = Effect.fn("makeHostResources")(function* () {
|
|
97097
98064
|
const fs = yield* FileSystem.FileSystem;
|
|
97098
98065
|
const platform = yield* HostProcessPlatform;
|
|
97099
98066
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
@@ -97127,7 +98094,7 @@ const make$65 = Effect.fn("makeHostResources")(function* () {
|
|
|
97127
98094
|
});
|
|
97128
98095
|
return HostResources.of({ read: Cache.get(cache, "host") });
|
|
97129
98096
|
});
|
|
97130
|
-
const layer$
|
|
98097
|
+
const layer$57 = Layer.effect(HostResources, make$66());
|
|
97131
98098
|
//#endregion
|
|
97132
98099
|
//#region src/resourceTelemetry/DesktopTelemetryReceiver.ts
|
|
97133
98100
|
const INITIAL_SAMPLE_DEADLINE_MS = 9e4;
|
|
@@ -97262,7 +98229,7 @@ function requireDesktopTelemetryWriteProgress(fd, remainingBytes, written) {
|
|
|
97262
98229
|
}));
|
|
97263
98230
|
}
|
|
97264
98231
|
/** @public Service construction is part of the canonical Effect module API. */
|
|
97265
|
-
const make$
|
|
98232
|
+
const make$65 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(function* () {
|
|
97266
98233
|
const serverConfig = yield* ServerConfig$1;
|
|
97267
98234
|
const hasDescriptors = serverConfig.mode === "desktop" && serverConfig.desktopTelemetryFd === 4 && serverConfig.desktopTelemetryControlFd === 5;
|
|
97268
98235
|
const config = {
|
|
@@ -97419,7 +98386,7 @@ const make$64 = Effect.fn("resourceTelemetry.desktopTelemetryReceiver.make")(fun
|
|
|
97419
98386
|
setDiagnosticsDemand
|
|
97420
98387
|
});
|
|
97421
98388
|
});
|
|
97422
|
-
const layer$
|
|
98389
|
+
const layer$56 = Layer.effect(DesktopTelemetryReceiver, make$65());
|
|
97423
98390
|
//#endregion
|
|
97424
98391
|
//#region src/resourceTelemetry/Model.ts
|
|
97425
98392
|
const MAX_DELTA_INTERVAL_MS = 3e4;
|
|
@@ -97844,7 +98811,7 @@ function resourceMonitorRustTarget(platform, architecture, linuxLibc) {
|
|
|
97844
98811
|
}
|
|
97845
98812
|
if (platform === "win32") return architecture === "arm64" ? "aarch64-pc-windows-msvc" : architecture === "x64" ? "x86_64-pc-windows-msvc" : void 0;
|
|
97846
98813
|
}
|
|
97847
|
-
const make$
|
|
98814
|
+
const make$64 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(function* () {
|
|
97848
98815
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
97849
98816
|
const path = yield* Path$1.Path;
|
|
97850
98817
|
const platform = yield* HostProcessPlatform;
|
|
@@ -97890,7 +98857,7 @@ const make$63 = Effect.fn("resourceTelemetry.resourceMonitorBinary.make")(functi
|
|
|
97890
98857
|
});
|
|
97891
98858
|
return ResourceMonitorBinary.of({ resolve });
|
|
97892
98859
|
});
|
|
97893
|
-
const layer$
|
|
98860
|
+
const layer$55 = Layer.effect(ResourceMonitorBinary, make$64());
|
|
97894
98861
|
//#endregion
|
|
97895
98862
|
//#region src/resourceTelemetry/NativeTelemetryClient.ts
|
|
97896
98863
|
const SAMPLE_INTERVAL_MS$1 = 1e3;
|
|
@@ -98040,7 +99007,7 @@ function canCommandNativeTelemetrySidecar(status, hasHandle) {
|
|
|
98040
99007
|
return hasHandle && (status === "healthy" || status === "degraded");
|
|
98041
99008
|
}
|
|
98042
99009
|
/** @public Service construction is part of the canonical Effect module API. */
|
|
98043
|
-
const make$
|
|
99010
|
+
const make$63 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(function* () {
|
|
98044
99011
|
const binary = yield* ResourceMonitorBinary;
|
|
98045
99012
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
98046
99013
|
const crypto = yield* Crypto.Crypto;
|
|
@@ -98451,7 +99418,7 @@ const make$62 = Effect.fn("resourceTelemetry.nativeTelemetryClient.make")(functi
|
|
|
98451
99418
|
})
|
|
98452
99419
|
});
|
|
98453
99420
|
});
|
|
98454
|
-
const layer$
|
|
99421
|
+
const layer$54 = Layer.effect(NativeTelemetryClient, make$63());
|
|
98455
99422
|
//#endregion
|
|
98456
99423
|
//#region src/resourceTelemetry/ResourceAttribution.ts
|
|
98457
99424
|
var ResourceAttribution = class extends Context.Service()("@p4code/cli/resourceTelemetry/ResourceAttribution") {};
|
|
@@ -98463,7 +99430,7 @@ function nonNegativeInteger(value, fallback) {
|
|
|
98463
99430
|
if (!Number.isFinite(value)) return 0;
|
|
98464
99431
|
return Math.max(0, Math.round(value));
|
|
98465
99432
|
}
|
|
98466
|
-
const make$
|
|
99433
|
+
const make$62 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function* () {
|
|
98467
99434
|
const entries = yield* Ref.make(/* @__PURE__ */ new Map());
|
|
98468
99435
|
const record = (input) => Ref.update(entries, (current) => {
|
|
98469
99436
|
const next = new Map(current);
|
|
@@ -98489,7 +99456,7 @@ const make$61 = Effect.fn("resourceTelemetry.resourceAttribution.make")(function
|
|
|
98489
99456
|
})
|
|
98490
99457
|
});
|
|
98491
99458
|
});
|
|
98492
|
-
const layer$
|
|
99459
|
+
const layer$53 = Layer.effect(ResourceAttribution, make$62());
|
|
98493
99460
|
//#endregion
|
|
98494
99461
|
//#region src/resourceTelemetry/ResourceTelemetryHistory.ts
|
|
98495
99462
|
const MAX_HISTORY_WINDOW_MS = 60 * 6e4;
|
|
@@ -98712,7 +99679,7 @@ function buildHealth(input) {
|
|
|
98712
99679
|
};
|
|
98713
99680
|
}
|
|
98714
99681
|
/** @public Service construction is part of the canonical Effect module API. */
|
|
98715
|
-
const make$
|
|
99682
|
+
const make$61 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function* () {
|
|
98716
99683
|
const nativeClient = yield* NativeTelemetryClient;
|
|
98717
99684
|
const desktopReceiver = yield* DesktopTelemetryReceiver;
|
|
98718
99685
|
const attribution = yield* ResourceAttribution;
|
|
@@ -98964,7 +99931,7 @@ const make$60 = Effect.fn("resourceTelemetry.resourceTelemetry.make")(function*
|
|
|
98964
99931
|
})))
|
|
98965
99932
|
});
|
|
98966
99933
|
});
|
|
98967
|
-
const layer$
|
|
99934
|
+
const layer$52 = Layer.effect(ResourceTelemetry, make$61());
|
|
98968
99935
|
//#endregion
|
|
98969
99936
|
//#region src/device/DeviceInspection.ts
|
|
98970
99937
|
const READ_TIMEOUT_MS = 1e4;
|
|
@@ -102119,7 +103086,7 @@ const classifyNonZeroExit = (command, stderr) => {
|
|
|
102119
103086
|
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";
|
|
102120
103087
|
return "command-failed";
|
|
102121
103088
|
};
|
|
102122
|
-
const make$
|
|
103089
|
+
const make$60 = Effect.gen(function* () {
|
|
102123
103090
|
const processRunner = yield* ProcessRunner;
|
|
102124
103091
|
const run = Effect.fn("VcsProcess.run")(function* (input) {
|
|
102125
103092
|
const baseError = {
|
|
@@ -102178,7 +103145,7 @@ const make$59 = Effect.gen(function* () {
|
|
|
102178
103145
|
});
|
|
102179
103146
|
return VcsProcess.of({ run });
|
|
102180
103147
|
});
|
|
102181
|
-
const layer$
|
|
103148
|
+
const layer$51 = Layer.effect(VcsProcess, make$60).pipe(Layer.provide(layer$82));
|
|
102182
103149
|
//#endregion
|
|
102183
103150
|
//#region src/vcs/VcsDriver.ts
|
|
102184
103151
|
var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
|
|
@@ -102629,12 +103596,12 @@ const makeVcsDriver = Effect.gen(function* () {
|
|
|
102629
103596
|
const driver = yield* makeVcsDriverShape();
|
|
102630
103597
|
return VcsDriver.of(driver);
|
|
102631
103598
|
});
|
|
102632
|
-
const make$
|
|
103599
|
+
const make$59 = Effect.gen(function* () {
|
|
102633
103600
|
const git = yield* makeGitVcsDriverCore();
|
|
102634
103601
|
return GitVcsDriver.of(git);
|
|
102635
103602
|
});
|
|
102636
103603
|
Layer.effect(VcsDriver, makeVcsDriver);
|
|
102637
|
-
const layer$
|
|
103604
|
+
const layer$50 = Layer.effect(GitVcsDriver, make$59);
|
|
102638
103605
|
//#endregion
|
|
102639
103606
|
//#region src/vcs/VcsProjectConfig.ts
|
|
102640
103607
|
const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
|
|
@@ -102666,7 +103633,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
|
|
|
102666
103633
|
configPath: error.configPath,
|
|
102667
103634
|
errorTag: error._tag
|
|
102668
103635
|
}));
|
|
102669
|
-
const make$
|
|
103636
|
+
const make$58 = Effect.gen(function* () {
|
|
102670
103637
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
102671
103638
|
const path = yield* Path$1.Path;
|
|
102672
103639
|
const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
|
|
@@ -102707,7 +103674,7 @@ const make$57 = Effect.gen(function* () {
|
|
|
102707
103674
|
});
|
|
102708
103675
|
return VcsProjectConfig.of({ resolveKind });
|
|
102709
103676
|
});
|
|
102710
|
-
const layer$
|
|
103677
|
+
const layer$49 = Layer.effect(VcsProjectConfig, make$58);
|
|
102711
103678
|
//#endregion
|
|
102712
103679
|
//#region src/vcs/VcsDriverRegistry.ts
|
|
102713
103680
|
const DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -102727,7 +103694,7 @@ function parseDetectionCacheKey(key) {
|
|
|
102727
103694
|
cwd: key.slice(separatorIndex + 1)
|
|
102728
103695
|
};
|
|
102729
103696
|
}
|
|
102730
|
-
const make$
|
|
103697
|
+
const make$57 = Effect.gen(function* () {
|
|
102731
103698
|
const projectConfig = yield* VcsProjectConfig;
|
|
102732
103699
|
const git = yield* makeVcsDriver;
|
|
102733
103700
|
const drivers = { git };
|
|
@@ -102784,7 +103751,7 @@ const make$56 = Effect.gen(function* () {
|
|
|
102784
103751
|
resolve
|
|
102785
103752
|
});
|
|
102786
103753
|
});
|
|
102787
|
-
const layer$
|
|
103754
|
+
const layer$48 = Layer.effect(VcsDriverRegistry, make$57).pipe(Layer.provide(layer$49));
|
|
102788
103755
|
//#endregion
|
|
102789
103756
|
//#region src/checkpointing/CheckpointStore.ts
|
|
102790
103757
|
/**
|
|
@@ -102804,7 +103771,7 @@ const layer$47 = Layer.effect(VcsDriverRegistry, make$56).pipe(Layer.provide(lay
|
|
|
102804
103771
|
*/
|
|
102805
103772
|
/** Service tag for checkpoint persistence and restore operations. */
|
|
102806
103773
|
var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
|
|
102807
|
-
const make$
|
|
103774
|
+
const make$56 = Effect.gen(function* () {
|
|
102808
103775
|
const vcsRegistry = yield* VcsDriverRegistry;
|
|
102809
103776
|
const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
|
|
102810
103777
|
const handle = yield* vcsRegistry.resolve({ cwd });
|
|
@@ -102843,7 +103810,7 @@ const make$55 = Effect.gen(function* () {
|
|
|
102843
103810
|
deleteCheckpointRefs
|
|
102844
103811
|
});
|
|
102845
103812
|
});
|
|
102846
|
-
const layer$
|
|
103813
|
+
const layer$47 = Layer.effect(CheckpointStore, make$56);
|
|
102847
103814
|
//#endregion
|
|
102848
103815
|
//#region src/checkpointing/CheckpointDiffQuery.ts
|
|
102849
103816
|
/**
|
|
@@ -102865,7 +103832,7 @@ function buildTurnDiffResult(input, diff) {
|
|
|
102865
103832
|
diff
|
|
102866
103833
|
};
|
|
102867
103834
|
}
|
|
102868
|
-
const make$
|
|
103835
|
+
const make$55 = Effect.gen(function* () {
|
|
102869
103836
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
102870
103837
|
const checkpointStore = yield* CheckpointStore;
|
|
102871
103838
|
const threadActivities = yield* ProjectionThreadActivityRepository;
|
|
@@ -103036,7 +104003,7 @@ const make$54 = Effect.gen(function* () {
|
|
|
103036
104003
|
getFullThreadDiff
|
|
103037
104004
|
});
|
|
103038
104005
|
});
|
|
103039
|
-
const layer$
|
|
104006
|
+
const layer$46 = Layer.effect(CheckpointDiffQuery, make$55);
|
|
103040
104007
|
//#endregion
|
|
103041
104008
|
//#region src/orchestration/ThreadLiveEventCoalescer.ts
|
|
103042
104009
|
const COALESCE_WINDOW = Duration.millis(50);
|
|
@@ -103581,7 +104548,7 @@ const serversEqual = (left, right) => {
|
|
|
103581
104548
|
}
|
|
103582
104549
|
return true;
|
|
103583
104550
|
};
|
|
103584
|
-
const make$
|
|
104551
|
+
const make$54 = Effect.gen(function* PortDiscoveryMake() {
|
|
103585
104552
|
const net = yield* NetService;
|
|
103586
104553
|
const processRunner = yield* ProcessRunner;
|
|
103587
104554
|
const hostPlatform = yield* HostProcessPlatform;
|
|
@@ -103732,7 +104699,7 @@ const make$53 = Effect.gen(function* PortDiscoveryMake() {
|
|
|
103732
104699
|
unregisterTerminal
|
|
103733
104700
|
});
|
|
103734
104701
|
}).pipe(Effect.withSpan("PortDiscovery.make"));
|
|
103735
|
-
const layer$
|
|
104702
|
+
const layer$45 = Layer.effect(PortDiscovery, make$54);
|
|
103736
104703
|
//#endregion
|
|
103737
104704
|
//#region src/terminal/Manager.ts
|
|
103738
104705
|
/**
|
|
@@ -104410,7 +105377,7 @@ function normalizedRuntimeEnv(env) {
|
|
|
104410
105377
|
if (entries.length === 0) return null;
|
|
104411
105378
|
return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
|
|
104412
105379
|
}
|
|
104413
|
-
const make$
|
|
105380
|
+
const make$53 = Effect.fn("TerminalManager.make")(function* () {
|
|
104414
105381
|
const { terminalLogsDir } = yield* ServerConfig$1;
|
|
104415
105382
|
const ptyAdapter = yield* PtyAdapter;
|
|
104416
105383
|
const portDiscovery = yield* PortDiscovery;
|
|
@@ -105372,7 +106339,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
|
|
|
105372
106339
|
subscribeMetadata
|
|
105373
106340
|
});
|
|
105374
106341
|
});
|
|
105375
|
-
const layer$
|
|
106342
|
+
const layer$44 = Layer.effect(TerminalManager, make$53()).pipe(Layer.provide(layer$82));
|
|
105376
106343
|
//#endregion
|
|
105377
106344
|
//#region src/project/ProjectSetupScriptRunner.ts
|
|
105378
106345
|
var ProjectSetupScriptOperationError = class extends Schema$1.TaggedErrorClass()("ProjectSetupScriptOperationError", {
|
|
@@ -105404,7 +106371,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
|
|
|
105404
106371
|
};
|
|
105405
106372
|
Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
|
|
105406
106373
|
var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
|
|
105407
|
-
const make$
|
|
106374
|
+
const make$52 = Effect.gen(function* () {
|
|
105408
106375
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
105409
106376
|
const terminalManager = yield* TerminalManager;
|
|
105410
106377
|
const settingsService = yield* Effect.serviceOption(ServerSettingsService);
|
|
@@ -105467,7 +106434,7 @@ const make$51 = Effect.gen(function* () {
|
|
|
105467
106434
|
});
|
|
105468
106435
|
return ProjectSetupScriptRunner.of({ runForThread });
|
|
105469
106436
|
});
|
|
105470
|
-
const layer$
|
|
106437
|
+
const layer$43 = Layer.effect(ProjectSetupScriptRunner, make$52);
|
|
105471
106438
|
//#endregion
|
|
105472
106439
|
//#region src/sourceControl/azureDevOpsPullRequests.ts
|
|
105473
106440
|
const AzureDevOpsPullRequestSchema = Schema$1.Struct({
|
|
@@ -105795,7 +106762,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
|
|
|
105795
106762
|
cause
|
|
105796
106763
|
})));
|
|
105797
106764
|
}
|
|
105798
|
-
const make$
|
|
106765
|
+
const make$51 = Effect.gen(function* () {
|
|
105799
106766
|
const process = yield* VcsProcess;
|
|
105800
106767
|
const execute = (input) => process.run({
|
|
105801
106768
|
operation: "AzureDevOpsCli.execute",
|
|
@@ -105937,7 +106904,7 @@ const make$50 = Effect.gen(function* () {
|
|
|
105937
106904
|
}).pipe(Effect.asVoid)
|
|
105938
106905
|
});
|
|
105939
106906
|
});
|
|
105940
|
-
const layer$
|
|
106907
|
+
const layer$42 = Layer.effect(AzureDevOpsCli, make$51);
|
|
105941
106908
|
//#endregion
|
|
105942
106909
|
//#region src/sourceControl/SourceControlProviderDiscovery.ts
|
|
105943
106910
|
function firstNonEmptyLine(text) {
|
|
@@ -106141,7 +107108,7 @@ function toChangeRequest$5(summary) {
|
|
|
106141
107108
|
isCrossRepository: false
|
|
106142
107109
|
};
|
|
106143
107110
|
}
|
|
106144
|
-
const make$
|
|
107111
|
+
const make$50 = Effect.gen(function* () {
|
|
106145
107112
|
const azure = yield* AzureDevOpsCli;
|
|
106146
107113
|
return SourceControlProvider.of({
|
|
106147
107114
|
kind: "azure-devops",
|
|
@@ -106234,7 +107201,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
106234
107201
|
})))
|
|
106235
107202
|
});
|
|
106236
107203
|
});
|
|
106237
|
-
Layer.effect(SourceControlProvider, make$
|
|
107204
|
+
Layer.effect(SourceControlProvider, make$50);
|
|
106238
107205
|
//#endregion
|
|
106239
107206
|
//#region src/sourceControl/bitbucketPullRequests.ts
|
|
106240
107207
|
const BitbucketRepositoryRefSchema = Schema$1.Struct({
|
|
@@ -106611,7 +107578,7 @@ function responseError(operation, response) {
|
|
|
106611
107578
|
responseBodyLength: collected.text.length
|
|
106612
107579
|
}))));
|
|
106613
107580
|
}
|
|
106614
|
-
const make$
|
|
107581
|
+
const make$49 = Effect.gen(function* () {
|
|
106615
107582
|
const config = yield* BitbucketApiEnvConfig;
|
|
106616
107583
|
const httpClient = yield* HttpClient.HttpClient;
|
|
106617
107584
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
@@ -106827,7 +107794,7 @@ const make$48 = Effect.gen(function* () {
|
|
|
106827
107794
|
})))
|
|
106828
107795
|
});
|
|
106829
107796
|
});
|
|
106830
|
-
const layer$
|
|
107797
|
+
const layer$40 = Layer.effect(BitbucketApi, make$49);
|
|
106831
107798
|
//#endregion
|
|
106832
107799
|
//#region src/sourceControl/BitbucketSourceControlProvider.ts
|
|
106833
107800
|
function toChangeRequest$4(summary) {
|
|
@@ -106845,7 +107812,7 @@ function toChangeRequest$4(summary) {
|
|
|
106845
107812
|
...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
|
|
106846
107813
|
};
|
|
106847
107814
|
}
|
|
106848
|
-
const make$
|
|
107815
|
+
const make$48 = Effect.gen(function* () {
|
|
106849
107816
|
const bitbucket = yield* BitbucketApi;
|
|
106850
107817
|
return SourceControlProvider.of({
|
|
106851
107818
|
kind: "bitbucket",
|
|
@@ -106936,7 +107903,7 @@ const make$47 = Effect.gen(function* () {
|
|
|
106936
107903
|
})))
|
|
106937
107904
|
});
|
|
106938
107905
|
});
|
|
106939
|
-
Layer.effect(SourceControlProvider, make$
|
|
107906
|
+
Layer.effect(SourceControlProvider, make$48);
|
|
106940
107907
|
const makeDiscovery = Effect.gen(function* () {
|
|
106941
107908
|
return {
|
|
106942
107909
|
type: "api",
|
|
@@ -107184,7 +108151,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
|
|
|
107184
108151
|
sshUrl: `git@${fallbackHost}:${repository}.git`
|
|
107185
108152
|
};
|
|
107186
108153
|
}
|
|
107187
|
-
const make$
|
|
108154
|
+
const make$47 = Effect.gen(function* () {
|
|
107188
108155
|
const process = yield* VcsProcess;
|
|
107189
108156
|
const execute = (input) => process.run({
|
|
107190
108157
|
operation: "GitHubCli.execute",
|
|
@@ -107302,7 +108269,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
107302
108269
|
}).pipe(Effect.asVoid)
|
|
107303
108270
|
});
|
|
107304
108271
|
});
|
|
107305
|
-
const layer$
|
|
108272
|
+
const layer$38 = Layer.effect(GitHubCli, make$47);
|
|
107306
108273
|
//#endregion
|
|
107307
108274
|
//#region src/sourceControl/gitHubAuthStatus.ts
|
|
107308
108275
|
const GitHubAuthStatusAccountSchema = Schema$1.Struct({
|
|
@@ -107404,7 +108371,7 @@ const discovery$1 = {
|
|
|
107404
108371
|
parseAuth: parseGitHubAuth,
|
|
107405
108372
|
installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
|
|
107406
108373
|
};
|
|
107407
|
-
const make$
|
|
108374
|
+
const make$46 = Effect.gen(function* () {
|
|
107408
108375
|
const github = yield* GitHubCli;
|
|
107409
108376
|
const listChangeRequests = (input) => {
|
|
107410
108377
|
if (input.state === "open") return github.listOpenPullRequests({
|
|
@@ -107520,7 +108487,7 @@ const make$45 = Effect.gen(function* () {
|
|
|
107520
108487
|
})))
|
|
107521
108488
|
});
|
|
107522
108489
|
});
|
|
107523
|
-
Layer.effect(SourceControlProvider, make$
|
|
108490
|
+
Layer.effect(SourceControlProvider, make$46);
|
|
107524
108491
|
//#endregion
|
|
107525
108492
|
//#region src/sourceControl/gitLabMergeRequests.ts
|
|
107526
108493
|
const GitLabProjectReferenceSchema = Schema$1.Struct({
|
|
@@ -107839,7 +108806,7 @@ function parseRepositoryPath(repository) {
|
|
|
107839
108806
|
projectPath
|
|
107840
108807
|
};
|
|
107841
108808
|
}
|
|
107842
|
-
const make$
|
|
108809
|
+
const make$45 = Effect.gen(function* () {
|
|
107843
108810
|
const process = yield* VcsProcess;
|
|
107844
108811
|
const run = (input, mapError) => process.run({
|
|
107845
108812
|
operation: "GitLabCli.execute",
|
|
@@ -107990,7 +108957,7 @@ const make$44 = Effect.gen(function* () {
|
|
|
107990
108957
|
}).pipe(Effect.asVoid)
|
|
107991
108958
|
});
|
|
107992
108959
|
});
|
|
107993
|
-
const layer$
|
|
108960
|
+
const layer$36 = Layer.effect(GitLabCli, make$45);
|
|
107994
108961
|
//#endregion
|
|
107995
108962
|
//#region src/sourceControl/gitLabAuthStatus.ts
|
|
107996
108963
|
const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
|
|
@@ -108088,7 +109055,7 @@ const discovery = {
|
|
|
108088
109055
|
refineUnknownRemote: refineUnknownGitLabRemote,
|
|
108089
109056
|
installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
|
|
108090
109057
|
};
|
|
108091
|
-
const make$
|
|
109058
|
+
const make$44 = Effect.gen(function* () {
|
|
108092
109059
|
const gitlab = yield* GitLabCli;
|
|
108093
109060
|
return SourceControlProvider.of({
|
|
108094
109061
|
kind: "gitlab",
|
|
@@ -108177,7 +109144,7 @@ const make$43 = Effect.gen(function* () {
|
|
|
108177
109144
|
})))
|
|
108178
109145
|
});
|
|
108179
109146
|
});
|
|
108180
|
-
Layer.effect(SourceControlProvider, make$
|
|
109147
|
+
Layer.effect(SourceControlProvider, make$44);
|
|
108181
109148
|
//#endregion
|
|
108182
109149
|
//#region src/sourceControl/SourceControlProviderRegistry.ts
|
|
108183
109150
|
const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -108333,12 +109300,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
|
|
|
108333
109300
|
})), { concurrency: "unbounded" })
|
|
108334
109301
|
});
|
|
108335
109302
|
});
|
|
108336
|
-
const make$
|
|
108337
|
-
const github = yield* make$
|
|
108338
|
-
const gitlab = yield* make$
|
|
108339
|
-
const bitbucket = yield* make$
|
|
109303
|
+
const make$43 = Effect.gen(function* () {
|
|
109304
|
+
const github = yield* make$46;
|
|
109305
|
+
const gitlab = yield* make$44;
|
|
109306
|
+
const bitbucket = yield* make$48;
|
|
108340
109307
|
const bitbucketDiscovery = yield* makeDiscovery;
|
|
108341
|
-
const azureDevOps = yield* make$
|
|
109308
|
+
const azureDevOps = yield* make$50;
|
|
108342
109309
|
return yield* makeWithProviders([
|
|
108343
109310
|
{
|
|
108344
109311
|
kind: "github",
|
|
@@ -108362,7 +109329,7 @@ const make$42 = Effect.gen(function* () {
|
|
|
108362
109329
|
}
|
|
108363
109330
|
]);
|
|
108364
109331
|
});
|
|
108365
|
-
const layer$
|
|
109332
|
+
const layer$34 = Layer.effect(SourceControlProviderRegistry, make$43);
|
|
108366
109333
|
//#endregion
|
|
108367
109334
|
//#region src/sourceControl/PrTemplateDetection.ts
|
|
108368
109335
|
const TEMPLATE_MAX_BYTES = 8e3;
|
|
@@ -108733,7 +109700,7 @@ function toPullRequestHeadRemoteInfo(pr) {
|
|
|
108733
109700
|
...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
|
|
108734
109701
|
};
|
|
108735
109702
|
}
|
|
108736
|
-
const make$
|
|
109703
|
+
const make$42 = Effect.gen(function* () {
|
|
108737
109704
|
const gitCore = yield* GitVcsDriver;
|
|
108738
109705
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
108739
109706
|
const textGeneration = yield* TextGeneration;
|
|
@@ -109707,7 +110674,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
109707
110674
|
runStackedAction
|
|
109708
110675
|
});
|
|
109709
110676
|
});
|
|
109710
|
-
const layer$
|
|
110677
|
+
const layer$33 = Layer.effect(GitManager, make$42);
|
|
109711
110678
|
//#endregion
|
|
109712
110679
|
//#region src/git/GitWorkflowService.ts
|
|
109713
110680
|
var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
|
|
@@ -109744,7 +110711,7 @@ function nonRepositoryListRefs() {
|
|
|
109744
110711
|
totalCount: 0
|
|
109745
110712
|
};
|
|
109746
110713
|
}
|
|
109747
|
-
const make$
|
|
110714
|
+
const make$41 = Effect.gen(function* () {
|
|
109748
110715
|
const registry = yield* VcsDriverRegistry;
|
|
109749
110716
|
const git = yield* GitVcsDriver;
|
|
109750
110717
|
const gitManager = yield* GitManager;
|
|
@@ -109830,7 +110797,7 @@ const make$40 = Effect.gen(function* () {
|
|
|
109830
110797
|
renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
|
|
109831
110798
|
});
|
|
109832
110799
|
});
|
|
109833
|
-
const layer$
|
|
110800
|
+
const layer$32 = Layer.effect(GitWorkflowService, make$41);
|
|
109834
110801
|
//#endregion
|
|
109835
110802
|
//#region src/pullRequest/PullRequestProvider.ts
|
|
109836
110803
|
/**
|
|
@@ -110191,7 +111158,7 @@ function isReviewerName(value) {
|
|
|
110191
111158
|
const name = value.trim();
|
|
110192
111159
|
return name.length > 0 && !name.startsWith("-");
|
|
110193
111160
|
}
|
|
110194
|
-
const make$
|
|
111161
|
+
const make$40 = Effect.gen(function* () {
|
|
110195
111162
|
const azure = yield* AzureDevOpsCli;
|
|
110196
111163
|
const detectArgs = ["--detect", "true"];
|
|
110197
111164
|
const executeJson = (input) => azure.execute({
|
|
@@ -110391,7 +111358,7 @@ const make$39 = Effect.gen(function* () {
|
|
|
110391
111358
|
}).pipe(Effect.asVoid)
|
|
110392
111359
|
});
|
|
110393
111360
|
});
|
|
110394
|
-
const layer$
|
|
111361
|
+
const layer$31 = Layer.effect(AzureDevOpsPullRequestCli, make$40);
|
|
110395
111362
|
//#endregion
|
|
110396
111363
|
//#region src/pullRequest/AzureDevOpsPullRequestProvider.ts
|
|
110397
111364
|
const CAPABILITIES$3 = {
|
|
@@ -110466,7 +111433,7 @@ function toChangeRequest$1(pullRequest) {
|
|
|
110466
111433
|
labels: []
|
|
110467
111434
|
};
|
|
110468
111435
|
}
|
|
110469
|
-
const make$
|
|
111436
|
+
const make$39 = Effect.gen(function* () {
|
|
110470
111437
|
const cli = yield* AzureDevOpsPullRequestCli;
|
|
110471
111438
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
110472
111439
|
provider: "azure-devops",
|
|
@@ -111206,7 +112173,7 @@ function mergeStrategy(method) {
|
|
|
111206
112173
|
default: return "merge_commit";
|
|
111207
112174
|
}
|
|
111208
112175
|
}
|
|
111209
|
-
const make$
|
|
112176
|
+
const make$38 = Effect.gen(function* () {
|
|
111210
112177
|
const bitbucket = yield* BitbucketApi;
|
|
111211
112178
|
/**
|
|
111212
112179
|
* The repository's own path, and the workspace above it — which the people who may review are
|
|
@@ -111486,7 +112453,7 @@ const make$37 = Effect.gen(function* () {
|
|
|
111486
112453
|
}).pipe(Effect.asVoid))
|
|
111487
112454
|
});
|
|
111488
112455
|
});
|
|
111489
|
-
const layer$
|
|
112456
|
+
const layer$30 = Layer.effect(BitbucketPullRequestApi, make$38);
|
|
111490
112457
|
//#endregion
|
|
111491
112458
|
//#region src/pullRequest/BitbucketPullRequestProvider.ts
|
|
111492
112459
|
const CAPABILITIES$2 = {
|
|
@@ -111566,7 +112533,7 @@ function toChangeRequest(pullRequest) {
|
|
|
111566
112533
|
labels: []
|
|
111567
112534
|
};
|
|
111568
112535
|
}
|
|
111569
|
-
const make$
|
|
112536
|
+
const make$37 = Effect.gen(function* () {
|
|
111570
112537
|
const api = yield* BitbucketPullRequestApi;
|
|
111571
112538
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
111572
112539
|
provider: "bitbucket",
|
|
@@ -113795,7 +114762,7 @@ function actionArgs$1(action, mergeMethod, updateMethod) {
|
|
|
113795
114762
|
case "reopen": return ["reopen"];
|
|
113796
114763
|
}
|
|
113797
114764
|
}
|
|
113798
|
-
const make$
|
|
114765
|
+
const make$36 = Effect.gen(function* () {
|
|
113799
114766
|
const github = yield* GitHubCli;
|
|
113800
114767
|
/**
|
|
113801
114768
|
* The pull request's own node id, which is what a mutation against the pull request itself is
|
|
@@ -114558,7 +115525,7 @@ const make$35 = Effect.gen(function* () {
|
|
|
114558
115525
|
})))
|
|
114559
115526
|
});
|
|
114560
115527
|
});
|
|
114561
|
-
const layer$
|
|
115528
|
+
const layer$29 = Layer.effect(GitHubPullRequestCli, make$36);
|
|
114562
115529
|
//#endregion
|
|
114563
115530
|
//#region src/pullRequest/GitHubPullRequestProvider.ts
|
|
114564
115531
|
const CAPABILITIES$1 = {
|
|
@@ -114675,7 +115642,7 @@ function loginAvatarUrl(login, host) {
|
|
|
114675
115642
|
}
|
|
114676
115643
|
/** True where markdown would render nothing: whitespace, or only HTML comments. */
|
|
114677
115644
|
const rendersEmpty = (body) => body.replace(/<!--[\s\S]*?-->/g, "").trim().length === 0;
|
|
114678
|
-
const make$
|
|
115645
|
+
const make$35 = Effect.gen(function* () {
|
|
114679
115646
|
const cli = yield* GitHubPullRequestCli;
|
|
114680
115647
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
114681
115648
|
provider: "github",
|
|
@@ -115697,7 +116664,7 @@ function actionArgs(action, mergeMethod) {
|
|
|
115697
116664
|
case "reopen": return ["reopen"];
|
|
115698
116665
|
}
|
|
115699
116666
|
}
|
|
115700
|
-
const make$
|
|
116667
|
+
const make$34 = Effect.gen(function* () {
|
|
115701
116668
|
const gitlab = yield* GitLabCli;
|
|
115702
116669
|
const api = (input) => gitlab.execute({
|
|
115703
116670
|
cwd: input.cwd,
|
|
@@ -116268,7 +117235,7 @@ const make$33 = Effect.gen(function* () {
|
|
|
116268
117235
|
}).pipe(Effect.asVoid)
|
|
116269
117236
|
});
|
|
116270
117237
|
});
|
|
116271
|
-
const layer$
|
|
117238
|
+
const layer$28 = Layer.effect(GitLabPullRequestCli, make$34);
|
|
116272
117239
|
//#endregion
|
|
116273
117240
|
//#region src/pullRequest/GitLabPullRequestProvider.ts
|
|
116274
117241
|
const CAPABILITIES = {
|
|
@@ -116348,7 +117315,7 @@ function reasonFor(error) {
|
|
|
116348
117315
|
if (error._tag === "GitLabCliAuthenticationError") return "unauthenticated";
|
|
116349
117316
|
return "failed";
|
|
116350
117317
|
}
|
|
116351
|
-
const make$
|
|
117318
|
+
const make$33 = Effect.gen(function* () {
|
|
116352
117319
|
const cli = yield* GitLabPullRequestCli;
|
|
116353
117320
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
116354
117321
|
provider: "gitlab",
|
|
@@ -116491,13 +117458,13 @@ function fromProviders(providers) {
|
|
|
116491
117458
|
* The hosts this build can read change requests from. A host with no entry here still shows up
|
|
116492
117459
|
* in the provider list as unimplemented, so its projects are explained rather than missing.
|
|
116493
117460
|
*/
|
|
116494
|
-
const make$
|
|
116495
|
-
make$
|
|
116496
|
-
make$
|
|
116497
|
-
make$
|
|
116498
|
-
make$
|
|
117461
|
+
const make$32 = Effect.map(Effect.all([
|
|
117462
|
+
make$35,
|
|
117463
|
+
make$33,
|
|
117464
|
+
make$37,
|
|
117465
|
+
make$39
|
|
116499
117466
|
]), fromProviders);
|
|
116500
|
-
const layer$
|
|
117467
|
+
const layer$27 = Layer.effect(PullRequestProviderRegistry, make$32).pipe(Layer.provide(layer$29.pipe(Layer.provide(layer$38))), Layer.provide(layer$28.pipe(Layer.provide(layer$36))), Layer.provide(layer$30.pipe(Layer.provide(layer$40))), Layer.provide(layer$31.pipe(Layer.provide(layer$42))));
|
|
116501
117468
|
//#endregion
|
|
116502
117469
|
//#region src/pullRequest/PullRequestService.ts
|
|
116503
117470
|
/**
|
|
@@ -116685,7 +117652,7 @@ function repositoryIdentityOf(project) {
|
|
|
116685
117652
|
if (identity.displayName) return identity.displayName;
|
|
116686
117653
|
return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null;
|
|
116687
117654
|
}
|
|
116688
|
-
const make$
|
|
117655
|
+
const make$31 = Effect.gen(function* () {
|
|
116689
117656
|
const registry = yield* PullRequestProviderRegistry;
|
|
116690
117657
|
const projections = yield* ProjectionSnapshotQuery;
|
|
116691
117658
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
@@ -117683,7 +118650,7 @@ const make$30 = Effect.gen(function* () {
|
|
|
117683
118650
|
invalidate
|
|
117684
118651
|
});
|
|
117685
118652
|
});
|
|
117686
|
-
const layer$
|
|
118653
|
+
const layer$26 = Layer.effect(PullRequestService, make$31);
|
|
117687
118654
|
//#endregion
|
|
117688
118655
|
//#region src/orchestration/ThreadWorkspaceLifecycle.ts
|
|
117689
118656
|
var ThreadWorkspaceLifecycleError = class extends Data.TaggedError("ThreadWorkspaceLifecycleError") {};
|
|
@@ -117727,7 +118694,7 @@ const mapLifecycleError = Effect.mapError((cause) => cause instanceof ThreadWork
|
|
|
117727
118694
|
detail: "Thread workspace lifecycle operation failed.",
|
|
117728
118695
|
cause
|
|
117729
118696
|
}));
|
|
117730
|
-
const make$
|
|
118697
|
+
const make$30 = Effect.gen(function* () {
|
|
117731
118698
|
const snapshots = yield* ProjectionSnapshotQuery;
|
|
117732
118699
|
const engine = yield* OrchestrationEngineService;
|
|
117733
118700
|
const gitWorkflow = yield* GitWorkflowService;
|
|
@@ -117981,7 +118948,7 @@ const make$29 = Effect.gen(function* () {
|
|
|
117981
118948
|
record
|
|
117982
118949
|
};
|
|
117983
118950
|
});
|
|
117984
|
-
const layer$
|
|
118951
|
+
const layer$25 = Layer.effect(ThreadWorkspaceLifecycleService, make$30);
|
|
117985
118952
|
//#endregion
|
|
117986
118953
|
//#region src/textGeneration/BtwRequestCoordinator.ts
|
|
117987
118954
|
const MAX_PENDING_BTW_CANCELLATIONS = 256;
|
|
@@ -120254,7 +121221,7 @@ function makeUpdateState(input) {
|
|
|
120254
121221
|
output: input.output ?? null
|
|
120255
121222
|
};
|
|
120256
121223
|
}
|
|
120257
|
-
const make$
|
|
121224
|
+
const make$29 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
120258
121225
|
const providerRegistry = yield* ProviderRegistry;
|
|
120259
121226
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
120260
121227
|
const httpClient = yield* HttpClient.HttpClient;
|
|
@@ -120369,7 +121336,7 @@ const make$28 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
|
120369
121336
|
});
|
|
120370
121337
|
return ProviderMaintenanceRunner.of({ updateProvider });
|
|
120371
121338
|
});
|
|
120372
|
-
const layer$
|
|
121339
|
+
const layer$24 = Layer.effect(ProviderMaintenanceRunner, make$29());
|
|
120373
121340
|
//#endregion
|
|
120374
121341
|
//#region src/usage/usageTranscripts.ts
|
|
120375
121342
|
const EMPTY_TOTALS = {
|
|
@@ -121176,29 +122143,33 @@ const ScanCacheJson = Schema$1.fromJsonString(Schema$1.Unknown);
|
|
|
121176
122143
|
const decodeScanCacheFile = Schema$1.decodeUnknownEffect(ScanCacheJson);
|
|
121177
122144
|
const encodeScanCacheFile = Schema$1.encodeEffect(ScanCacheJson);
|
|
121178
122145
|
var UsageService = class extends Context.Service()("@p4code/cli/usage/UsageService") {};
|
|
121179
|
-
Layer.succeed(UsageService, UsageService.of({
|
|
121180
|
-
|
|
121181
|
-
|
|
121182
|
-
|
|
121183
|
-
|
|
121184
|
-
|
|
121185
|
-
|
|
121186
|
-
|
|
121187
|
-
|
|
121188
|
-
|
|
121189
|
-
|
|
121190
|
-
|
|
121191
|
-
|
|
121192
|
-
|
|
121193
|
-
|
|
121194
|
-
}
|
|
121195
|
-
|
|
122146
|
+
Layer.succeed(UsageService, UsageService.of({
|
|
122147
|
+
readSessionRecords: () => Effect.succeed([]),
|
|
122148
|
+
readSummary: (input) => Effect.succeed({
|
|
122149
|
+
contractVersion: 4,
|
|
122150
|
+
readAt: "1970-01-01T00:00:00.000Z",
|
|
122151
|
+
timeZone: input.timeZone,
|
|
122152
|
+
sinceDay: input.sinceDay,
|
|
122153
|
+
untilDay: input.untilDay,
|
|
122154
|
+
buckets: [],
|
|
122155
|
+
sources: [],
|
|
122156
|
+
pricing: {
|
|
122157
|
+
status: "unavailable",
|
|
122158
|
+
source: LITELLM_RATES_URL,
|
|
122159
|
+
fetchedAt: null,
|
|
122160
|
+
knownModels: 0
|
|
122161
|
+
},
|
|
122162
|
+
scanDurationMs: 0
|
|
122163
|
+
})
|
|
122164
|
+
}));
|
|
122165
|
+
const make$28 = Effect.gen(function* () {
|
|
121196
122166
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
121197
122167
|
const path = yield* Path$1.Path;
|
|
121198
122168
|
const config = yield* ServerConfig$1;
|
|
121199
122169
|
const settingsService = yield* ServerSettingsService;
|
|
121200
122170
|
const httpClient = yield* HttpClient.HttpClient;
|
|
121201
122171
|
const fileCache = /* @__PURE__ */ new Map();
|
|
122172
|
+
const scanLock = yield* Semaphore.make(1);
|
|
121202
122173
|
let cacheDirty = false;
|
|
121203
122174
|
const ratesCachePath = path.join(config.stateDir, "usage-model-rates.json");
|
|
121204
122175
|
const scanCachePath = path.join(config.stateDir, "usage-scan-cache.json");
|
|
@@ -121309,7 +122280,7 @@ const make$27 = Effect.gen(function* () {
|
|
|
121309
122280
|
cacheDirty = true;
|
|
121310
122281
|
return tailRecords.length === 0 ? records : [...records, ...tailRecords];
|
|
121311
122282
|
});
|
|
121312
|
-
|
|
122283
|
+
const readSummary = Effect.fn("UsageService.readSummary")(function* (input) {
|
|
121313
122284
|
if (input.sinceDay > input.untilDay) return yield* new UsageReadError({
|
|
121314
122285
|
reason: "invalidWindow",
|
|
121315
122286
|
detail: `sinceDay '${input.sinceDay}' is after untilDay '${input.untilDay}'`
|
|
@@ -121432,9 +122403,49 @@ const make$27 = Effect.gen(function* () {
|
|
|
121432
122403
|
},
|
|
121433
122404
|
scanDurationMs: Math.max(0, finishedAtMs - startedAtMs)
|
|
121434
122405
|
};
|
|
121435
|
-
})
|
|
122406
|
+
});
|
|
122407
|
+
const readSessionRecords = Effect.fn("UsageService.readSessionRecords")(function* (input) {
|
|
122408
|
+
if (input.sessionIds.length === 0) return [];
|
|
122409
|
+
yield* ensureScanCacheLoaded;
|
|
122410
|
+
const { dirs } = yield* resolveTranscriptDirs().pipe(Effect.provideService(Path$1.Path, path));
|
|
122411
|
+
const roots = dirs.flatMap((root) => root.provider === "codex" ? [root, {
|
|
122412
|
+
...root,
|
|
122413
|
+
dir: path.join(path.dirname(root.dir), "archived_sessions")
|
|
122414
|
+
}] : [root]);
|
|
122415
|
+
const sessions = new Set(input.sessionIds);
|
|
122416
|
+
const seen = /* @__PURE__ */ new Set();
|
|
122417
|
+
const records = [];
|
|
122418
|
+
for (const { provider, dir } of roots) {
|
|
122419
|
+
const files = yield* Effect.promise(() => listTranscriptFiles(dir, input.sinceMs - MTIME_SLACK_MS));
|
|
122420
|
+
for (const file of files) {
|
|
122421
|
+
if (!input.sessionIds.some((id) => file.path.includes(id))) continue;
|
|
122422
|
+
const rows = yield* readFileRecords(file.path, file.size, file.mtimeMs, provider);
|
|
122423
|
+
for (const record of rows) {
|
|
122424
|
+
if (!sessions.has(record.sessionId) || record.timestampMs < input.sinceMs) continue;
|
|
122425
|
+
if (record.dedupeKey !== null) {
|
|
122426
|
+
if (seen.has(record.dedupeKey)) continue;
|
|
122427
|
+
seen.add(record.dedupeKey);
|
|
122428
|
+
}
|
|
122429
|
+
records.push(record);
|
|
122430
|
+
}
|
|
122431
|
+
}
|
|
122432
|
+
}
|
|
122433
|
+
const now = yield* Clock.currentTimeMillis;
|
|
122434
|
+
if (pruneScanCache(fileCache, {
|
|
122435
|
+
livePaths: /* @__PURE__ */ new Set(),
|
|
122436
|
+
walkedRoots: [],
|
|
122437
|
+
windowStartMs: input.sinceMs,
|
|
122438
|
+
retentionCutoffMs: now - CACHE_RETENTION_DAYS * 24 * 60 * 60 * 1e3
|
|
122439
|
+
}) > 0) cacheDirty = true;
|
|
122440
|
+
yield* persistScanCache();
|
|
122441
|
+
return records;
|
|
122442
|
+
});
|
|
122443
|
+
return {
|
|
122444
|
+
readSummary: (input) => scanLock.withPermits(1)(readSummary(input)),
|
|
122445
|
+
readSessionRecords: (input) => scanLock.withPermits(1)(readSessionRecords(input))
|
|
122446
|
+
};
|
|
121436
122447
|
});
|
|
121437
|
-
const layer$
|
|
122448
|
+
const layer$23 = Layer.effect(UsageService, make$28);
|
|
121438
122449
|
//#endregion
|
|
121439
122450
|
//#region src/feed/FeedStore.ts
|
|
121440
122451
|
const storageFailure = (message) => new FeedError({
|
|
@@ -121798,7 +122809,7 @@ const jsonRequest = Effect.fn("FeedService.jsonRequest")(function* (url, token,
|
|
|
121798
122809
|
catch: () => fail("hub_unavailable", "Hub returned invalid JSON.")
|
|
121799
122810
|
});
|
|
121800
122811
|
});
|
|
121801
|
-
const make$
|
|
122812
|
+
const make$27 = Effect.gen(function* () {
|
|
121802
122813
|
const hubLink = yield* HubLink;
|
|
121803
122814
|
const providers = yield* ProviderInstanceRegistry;
|
|
121804
122815
|
const config = yield* ServerConfig$1;
|
|
@@ -122036,7 +123047,7 @@ var FeedService = class extends Context.Reference("@p4code/cli/feed/FeedService"
|
|
|
122036
123047
|
markRead: unavailable,
|
|
122037
123048
|
cleanup: unavailable
|
|
122038
123049
|
}) }) {};
|
|
122039
|
-
const layer$
|
|
123050
|
+
const layer$22 = Layer.effect(FeedService, make$27);
|
|
122040
123051
|
const SKILL_MANIFEST_FILENAME = "SKILL.md";
|
|
122041
123052
|
/**
|
|
122042
123053
|
* Split a catalogue id (`owner/repo/skill-name`) into its parts.
|
|
@@ -122182,7 +123193,7 @@ const emptyFetch = (id, unavailable) => ({
|
|
|
122182
123193
|
skipped: [],
|
|
122183
123194
|
unavailable
|
|
122184
123195
|
});
|
|
122185
|
-
const make$
|
|
123196
|
+
const make$26 = Effect.gen(function* () {
|
|
122186
123197
|
const http = yield* HttpClient.HttpClient;
|
|
122187
123198
|
const request = Effect.fn("SkillRegistry.request")(function* (url) {
|
|
122188
123199
|
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));
|
|
@@ -122253,7 +123264,7 @@ const make$25 = Effect.gen(function* () {
|
|
|
122253
123264
|
fetch
|
|
122254
123265
|
};
|
|
122255
123266
|
});
|
|
122256
|
-
const layer$
|
|
123267
|
+
const layer$21 = Layer.effect(SkillRegistry, make$26);
|
|
122257
123268
|
//#endregion
|
|
122258
123269
|
//#region src/mcp/PreviewAutomationBroker.ts
|
|
122259
123270
|
var PreviewAutomationBroker = class extends Context.Service()("@p4code/cli/mcp/PreviewAutomationBroker") {};
|
|
@@ -122371,7 +123382,7 @@ const classifyResponseError = (context, error) => {
|
|
|
122371
123382
|
});
|
|
122372
123383
|
}
|
|
122373
123384
|
};
|
|
122374
|
-
const make$
|
|
123385
|
+
const make$25 = Effect.gen(function* PreviewAutomationBrokerMake() {
|
|
122375
123386
|
const crypto = yield* Crypto.Crypto;
|
|
122376
123387
|
const state = yield* SynchronizedRef.make({
|
|
122377
123388
|
clients: /* @__PURE__ */ new Map(),
|
|
@@ -122605,7 +123616,7 @@ const make$24 = Effect.gen(function* PreviewAutomationBrokerMake() {
|
|
|
122605
123616
|
invoke
|
|
122606
123617
|
});
|
|
122607
123618
|
}).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
|
|
122608
|
-
const layer$
|
|
123619
|
+
const layer$20 = Layer.effect(PreviewAutomationBroker, make$25);
|
|
122609
123620
|
//#endregion
|
|
122610
123621
|
//#region src/preview/Manager.ts
|
|
122611
123622
|
/**
|
|
@@ -122669,7 +123680,7 @@ const buildIdleSnapshot = (input) => ({
|
|
|
122669
123680
|
viewport: FILL_PREVIEW_VIEWPORT,
|
|
122670
123681
|
updatedAt: input.updatedAt
|
|
122671
123682
|
});
|
|
122672
|
-
const make$
|
|
123683
|
+
const make$24 = Effect.gen(function* PreviewManagerMake() {
|
|
122673
123684
|
const serverEpoch = NodeCrypto.randomUUID();
|
|
122674
123685
|
const stateRef = yield* SynchronizedRef.make(initialState);
|
|
122675
123686
|
const eventsPubSub = yield* PubSub.unbounded();
|
|
@@ -122900,7 +123911,7 @@ const make$23 = Effect.gen(function* PreviewManagerMake() {
|
|
|
122900
123911
|
subscribeEvents: PubSub.subscribe(eventsPubSub)
|
|
122901
123912
|
});
|
|
122902
123913
|
}).pipe(Effect.withSpan("PreviewManager.make"));
|
|
122903
|
-
const layer$
|
|
123914
|
+
const layer$19 = Layer.effect(PreviewManager, make$24);
|
|
122904
123915
|
//#endregion
|
|
122905
123916
|
//#region src/workspace/WorkspaceSearchIndex.ts
|
|
122906
123917
|
const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
|
|
@@ -123037,7 +124048,7 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
|
|
|
123037
124048
|
timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
|
|
123038
124049
|
})
|
|
123039
124050
|
}), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
|
|
123040
|
-
const make$
|
|
124051
|
+
const make$23 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
|
|
123041
124052
|
const finder = yield* Effect.acquireRelease(createFinder(cwd, contentSearch), (finder) => Effect.try({
|
|
123042
124053
|
try: () => finder.destroy(),
|
|
123043
124054
|
catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
|
|
@@ -123177,14 +124188,14 @@ const make$22 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSe
|
|
|
123177
124188
|
* workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
|
|
123178
124189
|
* using a default cwd here would mix resources from different workspaces.
|
|
123179
124190
|
*/
|
|
123180
|
-
const layer$
|
|
124191
|
+
const layer$18 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$23(cwd));
|
|
123181
124192
|
var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
|
|
123182
|
-
lookup: layer$
|
|
124193
|
+
lookup: layer$18,
|
|
123183
124194
|
idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
|
|
123184
124195
|
}) {};
|
|
123185
124196
|
/** Content indexing is allocated only when workspace content search is used. */
|
|
123186
124197
|
var WorkspaceContentSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceContentSearchIndexMap", {
|
|
123187
|
-
lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$
|
|
124198
|
+
lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$23(cwd, true)),
|
|
123188
124199
|
idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
|
|
123189
124200
|
}) {};
|
|
123190
124201
|
//#endregion
|
|
@@ -123246,7 +124257,7 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
|
|
|
123246
124257
|
if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
|
|
123247
124258
|
return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
|
|
123248
124259
|
});
|
|
123249
|
-
const make$
|
|
124260
|
+
const make$22 = Effect.gen(function* () {
|
|
123250
124261
|
const path = yield* Path$1.Path;
|
|
123251
124262
|
const workspacePaths = yield* WorkspacePaths;
|
|
123252
124263
|
const contentSearchIndexes = yield* WorkspaceContentSearchIndexMap;
|
|
@@ -123328,7 +124339,7 @@ const make$21 = Effect.gen(function* () {
|
|
|
123328
124339
|
searchContents
|
|
123329
124340
|
});
|
|
123330
124341
|
});
|
|
123331
|
-
const layer$
|
|
124342
|
+
const layer$17 = Layer.effect(WorkspaceEntries, make$22).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
|
|
123332
124343
|
//#endregion
|
|
123333
124344
|
//#region src/workspace/WorkspaceFileSystem.ts
|
|
123334
124345
|
/**
|
|
@@ -123387,7 +124398,7 @@ Schema$1.Union([
|
|
|
123387
124398
|
]);
|
|
123388
124399
|
/** Service tag for workspace file operations. */
|
|
123389
124400
|
var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
|
|
123390
|
-
const make$
|
|
124401
|
+
const make$21 = Effect.gen(function* () {
|
|
123391
124402
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
123392
124403
|
const path = yield* Path$1.Path;
|
|
123393
124404
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -123531,7 +124542,7 @@ const make$20 = Effect.gen(function* () {
|
|
|
123531
124542
|
writeFile
|
|
123532
124543
|
});
|
|
123533
124544
|
});
|
|
123534
|
-
const layer$
|
|
124545
|
+
const layer$16 = Layer.effect(WorkspaceFileSystem, make$21);
|
|
123535
124546
|
//#endregion
|
|
123536
124547
|
//#region src/vcs/VcsStatusBroadcaster.ts
|
|
123537
124548
|
const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
|
|
@@ -123613,7 +124624,7 @@ const autoPullPolicyLayer = Layer.effect(VcsAutoPullPolicy, Effect.gen(function*
|
|
|
123613
124624
|
return resolveProjectAutoPull(yield* settingsService.getSettings, project.value.id);
|
|
123614
124625
|
}, Effect.orElseSucceed(() => false)) };
|
|
123615
124626
|
}));
|
|
123616
|
-
const make$
|
|
124627
|
+
const make$20 = Effect.gen(function* () {
|
|
123617
124628
|
const autoPullPolicy = yield* VcsAutoPullPolicy;
|
|
123618
124629
|
const workflow = yield* GitWorkflowService;
|
|
123619
124630
|
const fs = yield* FileSystem.FileSystem;
|
|
@@ -123872,7 +124883,7 @@ const make$19 = Effect.gen(function* () {
|
|
|
123872
124883
|
streamStatus
|
|
123873
124884
|
});
|
|
123874
124885
|
});
|
|
123875
|
-
const layer$
|
|
124886
|
+
const layer$15 = Layer.effect(VcsStatusBroadcaster, make$20);
|
|
123876
124887
|
//#endregion
|
|
123877
124888
|
//#region src/vcs/VcsProvisioningService.ts
|
|
123878
124889
|
var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
|
|
@@ -123885,7 +124896,7 @@ function resolveRequestedKind(kind) {
|
|
|
123885
124896
|
}));
|
|
123886
124897
|
return Effect.succeed(kind);
|
|
123887
124898
|
}
|
|
123888
|
-
const make$
|
|
124899
|
+
const make$19 = Effect.gen(function* () {
|
|
123889
124900
|
const registry = yield* VcsDriverRegistry;
|
|
123890
124901
|
const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
|
|
123891
124902
|
const kind = yield* resolveRequestedKind(input.kind);
|
|
@@ -123893,11 +124904,11 @@ const make$18 = Effect.gen(function* () {
|
|
|
123893
124904
|
});
|
|
123894
124905
|
return VcsProvisioningService.of({ initRepository });
|
|
123895
124906
|
});
|
|
123896
|
-
const layer$
|
|
124907
|
+
const layer$14 = Layer.effect(VcsProvisioningService, make$19);
|
|
123897
124908
|
//#endregion
|
|
123898
124909
|
//#region src/review/ReviewService.ts
|
|
123899
124910
|
var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
|
|
123900
|
-
const make$
|
|
124911
|
+
const make$18 = Effect.gen(function* () {
|
|
123901
124912
|
const config = yield* ServerConfig$1;
|
|
123902
124913
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
123903
124914
|
const path = yield* Path$1.Path;
|
|
@@ -123953,7 +124964,7 @@ const make$17 = Effect.gen(function* () {
|
|
|
123953
124964
|
});
|
|
123954
124965
|
return ReviewService.of({ getDiffPreview });
|
|
123955
124966
|
});
|
|
123956
|
-
const layer$
|
|
124967
|
+
const layer$13 = Layer.effect(ReviewService, make$18);
|
|
123957
124968
|
//#endregion
|
|
123958
124969
|
//#region src/diagnostics/ProcessDiagnostics.ts
|
|
123959
124970
|
const PROCESS_QUERY_TIMEOUT_MS = 1e3;
|
|
@@ -124248,7 +125259,7 @@ function assertDescendantPid(pid) {
|
|
|
124248
125259
|
}));
|
|
124249
125260
|
}));
|
|
124250
125261
|
}
|
|
124251
|
-
const make$
|
|
125262
|
+
const make$17 = Effect.gen(function* () {
|
|
124252
125263
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
124253
125264
|
const read = Effect.gen(function* () {
|
|
124254
125265
|
const readAt = yield* DateTime.now;
|
|
@@ -124292,7 +125303,7 @@ const make$16 = Effect.gen(function* () {
|
|
|
124292
125303
|
signal
|
|
124293
125304
|
});
|
|
124294
125305
|
});
|
|
124295
|
-
const layer$
|
|
125306
|
+
const layer$12 = Layer.effect(ProcessDiagnostics, make$17);
|
|
124296
125307
|
//#endregion
|
|
124297
125308
|
//#region src/diagnostics/ProcessResourceMonitor.ts
|
|
124298
125309
|
const SAMPLE_INTERVAL_MS = 5e3;
|
|
@@ -124443,7 +125454,7 @@ function aggregateProcessResourceHistory(input) {
|
|
|
124443
125454
|
}) : Option.none()
|
|
124444
125455
|
};
|
|
124445
125456
|
}
|
|
124446
|
-
const make$
|
|
125457
|
+
const make$16 = Effect.gen(function* () {
|
|
124447
125458
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
124448
125459
|
const state = yield* Ref.make({
|
|
124449
125460
|
samples: [],
|
|
@@ -124492,7 +125503,7 @@ const make$15 = Effect.gen(function* () {
|
|
|
124492
125503
|
});
|
|
124493
125504
|
return ProcessResourceMonitor.of({ readHistory });
|
|
124494
125505
|
});
|
|
124495
|
-
const layer$
|
|
125506
|
+
const layer$11 = Layer.effect(ProcessResourceMonitor, make$16);
|
|
124496
125507
|
//#endregion
|
|
124497
125508
|
//#region src/diagnostics/TraceDiagnostics.ts
|
|
124498
125509
|
var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
|
|
@@ -124740,7 +125751,7 @@ function readTraceFile(fileSystem, path) {
|
|
|
124740
125751
|
cause
|
|
124741
125752
|
})) }));
|
|
124742
125753
|
}
|
|
124743
|
-
const make$
|
|
125754
|
+
const make$15 = Effect.gen(function* () {
|
|
124744
125755
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
124745
125756
|
const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
|
|
124746
125757
|
const readAt = options.readAt ?? (yield* DateTime.now);
|
|
@@ -124784,7 +125795,7 @@ const make$14 = Effect.gen(function* () {
|
|
|
124784
125795
|
});
|
|
124785
125796
|
return TraceDiagnostics.of({ read });
|
|
124786
125797
|
});
|
|
124787
|
-
const layer$
|
|
125798
|
+
const layer$10 = Layer.effect(TraceDiagnostics, make$15);
|
|
124788
125799
|
function readTraceDiagnostics(options) {
|
|
124789
125800
|
return Effect.gen(function* () {
|
|
124790
125801
|
return yield* (yield* TraceDiagnostics).read(options);
|
|
@@ -124819,7 +125830,7 @@ function snapshotFromDetail(link, detail, syncedAt) {
|
|
|
124819
125830
|
mergeability: detail.mergeability
|
|
124820
125831
|
};
|
|
124821
125832
|
}
|
|
124822
|
-
const make$
|
|
125833
|
+
const make$14 = Effect.gen(function* () {
|
|
124823
125834
|
const engine = yield* OrchestrationEngineService;
|
|
124824
125835
|
const projections = yield* ProjectionSnapshotQuery;
|
|
124825
125836
|
const pullRequests = yield* PullRequestService;
|
|
@@ -124913,7 +125924,7 @@ const make$13 = Effect.gen(function* () {
|
|
|
124913
125924
|
};
|
|
124914
125925
|
});
|
|
124915
125926
|
var PullRequestSyncReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/PullRequestSyncReactor") {};
|
|
124916
|
-
const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$
|
|
125927
|
+
const PullRequestSyncReactorLive = Layer.effect(PullRequestSyncReactor, make$14);
|
|
124917
125928
|
//#endregion
|
|
124918
125929
|
//#region src/sourceControl/SourceControlDiscovery.ts
|
|
124919
125930
|
const VCS_PROBES = [{
|
|
@@ -124932,7 +125943,7 @@ const VCS_PROBES = [{
|
|
|
124932
125943
|
installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
|
|
124933
125944
|
}];
|
|
124934
125945
|
var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
|
|
124935
|
-
const make$
|
|
125946
|
+
const make$13 = Effect.gen(function* () {
|
|
124936
125947
|
const config = yield* ServerConfig$1;
|
|
124937
125948
|
const process = yield* VcsProcess;
|
|
124938
125949
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
@@ -124981,7 +125992,7 @@ const make$12 = Effect.gen(function* () {
|
|
|
124981
125992
|
sourceControlProviders: sourceControlProviders.discover
|
|
124982
125993
|
}) });
|
|
124983
125994
|
});
|
|
124984
|
-
const layer$
|
|
125995
|
+
const layer$9 = Layer.effect(SourceControlDiscovery, make$13);
|
|
124985
125996
|
//#endregion
|
|
124986
125997
|
//#region src/sourceControl/SourceControlRepositoryService.ts
|
|
124987
125998
|
const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
|
|
@@ -125014,7 +126025,7 @@ function expandHomePath(input, path) {
|
|
|
125014
126025
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
125015
126026
|
return input;
|
|
125016
126027
|
}
|
|
125017
|
-
const make$
|
|
126028
|
+
const make$12 = Effect.gen(function* () {
|
|
125018
126029
|
const config = yield* ServerConfig$1;
|
|
125019
126030
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
125020
126031
|
const git = yield* GitVcsDriver;
|
|
@@ -125153,7 +126164,7 @@ const make$11 = Effect.gen(function* () {
|
|
|
125153
126164
|
publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
|
|
125154
126165
|
});
|
|
125155
126166
|
});
|
|
125156
|
-
const layer$
|
|
126167
|
+
const layer$8 = Layer.effect(SourceControlRepositoryService, make$12);
|
|
125157
126168
|
//#endregion
|
|
125158
126169
|
//#region src/ws.ts
|
|
125159
126170
|
/** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
|
|
@@ -125300,6 +126311,7 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
|
|
|
125300
126311
|
[WS_METHODS.serverUpdateServer, AuthOrchestrationOperateScope],
|
|
125301
126312
|
[WS_METHODS.serverUpsertKeybinding, AuthOrchestrationOperateScope],
|
|
125302
126313
|
[WS_METHODS.serverRemoveKeybinding, AuthOrchestrationOperateScope],
|
|
126314
|
+
[WS_METHODS.threadHandoff, AuthOrchestrationReadScope],
|
|
125303
126315
|
[WS_METHODS.btwAsk, AuthOrchestrationReadScope],
|
|
125304
126316
|
[WS_METHODS.btwCancel, AuthOrchestrationReadScope],
|
|
125305
126317
|
[WS_METHODS.tasksList, AuthOrchestrationReadScope],
|
|
@@ -126152,6 +127164,27 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker, computerUseBrok
|
|
|
126152
127164
|
operation: "getUsageReport",
|
|
126153
127165
|
detail: "This provider does not report account usage."
|
|
126154
127166
|
})), { "rpc.aggregate": "server" }),
|
|
127167
|
+
[WS_METHODS.threadHandoff]: (input) => observeRpcEffect$1(WS_METHODS.threadHandoff, Effect.gen(function* () {
|
|
127168
|
+
const fail = (detail) => new TextGenerationError({
|
|
127169
|
+
operation: "createHandoff",
|
|
127170
|
+
detail
|
|
127171
|
+
});
|
|
127172
|
+
if (!projectionSnapshotQuery.getHandoffContext || !textGeneration.generateBtwAnswer) return yield* fail("Handoff generation is unavailable on this server.");
|
|
127173
|
+
const context = yield* projectionSnapshotQuery.getHandoffContext(input.threadId).pipe(Effect.mapError(() => fail("Could not read thread history.")));
|
|
127174
|
+
if (Option.isNone(context)) return yield* fail("Thread or project is no longer available.");
|
|
127175
|
+
const settings = yield* serverSettings.getSettings.pipe(Effect.mapError(() => fail("Could not read text generation settings.")));
|
|
127176
|
+
const result = yield* textGeneration.generateBtwAnswer({
|
|
127177
|
+
cwd: context.value.projectId === P4_CHAT_PROJECT_ID ? config.chatWorkspaceDir : context.value.cwd,
|
|
127178
|
+
modelSelection: settings.textGenerationModelSelection,
|
|
127179
|
+
context: context.value.transcript,
|
|
127180
|
+
question: "Write a self-contained handoff for a new coding-agent thread continuing this work. Include objective, latest user constraints, decisions, completed changes, verification evidence and its limits, pending work, important paths and identifiers. Reconcile builder and watcher histories without duplicating their shared facts. Later user corrections win. Preserve explicit authorization limits; do not invent approvals or claim missing work is complete. Histories may be bounded: say when earlier context is unavailable. Return only the handoff in concise Markdown, addressed to the next agent."
|
|
127181
|
+
});
|
|
127182
|
+
if (!result.answer.trim()) return yield* fail("Model returned an empty handoff. Try again.");
|
|
127183
|
+
return {
|
|
127184
|
+
projectId: context.value.projectId,
|
|
127185
|
+
text: result.answer.trim()
|
|
127186
|
+
};
|
|
127187
|
+
}), { "rpc.aggregate": "thread" }),
|
|
126155
127188
|
[WS_METHODS.btwAsk]: (input) => observeRpcEffect$1(WS_METHODS.btwAsk, btw ? btw.ask(input) : Effect.fail(new BtwAskError({ detail: "Contextual questions are unavailable on this server." })), { "rpc.aggregate": "server" }),
|
|
126156
127189
|
[WS_METHODS.btwCancel]: (input) => observeRpcEffect$1(WS_METHODS.btwCancel, btw ? btw.cancel(input) : Effect.succeed({}), { "rpc.aggregate": "server" }),
|
|
126157
127190
|
[WS_METHODS.serverGetUsageSummary]: (input) => observeRpcEffect$1(WS_METHODS.serverGetUsageSummary, usage.readSummary(input), { "rpc.aggregate": "server" }),
|
|
@@ -126593,7 +127626,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
126593
127626
|
const serverAuth = yield* EnvironmentAuth;
|
|
126594
127627
|
const sessions = yield* SessionStore;
|
|
126595
127628
|
const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
|
|
126596
|
-
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker, computerUseBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$
|
|
127629
|
+
const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker, computerUseBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$24), 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$9.pipe(Layer.provide(layer$34.pipe(Layer.provide(Layer.mergeAll(layer$42, layer$40, layer$38, layer$36)), Layer.provideMerge(layer$50), Layer.provide(layer$48.pipe(Layer.provide(layer$49))))), Layer.provide(layer$51))))));
|
|
126597
127630
|
return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
|
|
126598
127631
|
}).pipe(Effect.catchTags({
|
|
126599
127632
|
EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
|
|
@@ -126658,7 +127691,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
|
|
|
126658
127691
|
cause
|
|
126659
127692
|
});
|
|
126660
127693
|
}
|
|
126661
|
-
const make$
|
|
127694
|
+
const make$11 = Effect.gen(function* () {
|
|
126662
127695
|
const sql = yield* SqlClient.SqlClient;
|
|
126663
127696
|
const upsertRuntimeRow = SqlSchema.void({
|
|
126664
127697
|
Request: ProviderSessionRuntimeDbRowSchema,
|
|
@@ -126761,7 +127794,7 @@ const make$10 = Effect.gen(function* () {
|
|
|
126761
127794
|
deleteByThreadId
|
|
126762
127795
|
};
|
|
126763
127796
|
});
|
|
126764
|
-
const layer$
|
|
127797
|
+
const layer$7 = Layer.effect(ProviderSessionRuntimeRepository, make$11);
|
|
126765
127798
|
//#endregion
|
|
126766
127799
|
//#region src/provider/Layers/ProviderSessionDirectory.ts
|
|
126767
127800
|
const decodeProviderDriverKindValue = Schema$1.decodeUnknownEffect(ProviderDriverKind);
|
|
@@ -126912,6 +127945,13 @@ const makeProviderAdapterRegistry = Effect.fn("makeProviderAdapterRegistry")(fun
|
|
|
126912
127945
|
});
|
|
126913
127946
|
const ProviderAdapterRegistryLive = Layer.effect(ProviderAdapterRegistry, makeProviderAdapterRegistry());
|
|
126914
127947
|
//#endregion
|
|
127948
|
+
//#region src/provider/ComputerUsePrompts.ts
|
|
127949
|
+
/** Routing guidance is injected only when the session has P4's Computer Use endpoint. */
|
|
127950
|
+
const COMPUTER_USE_ROUTING_PROMPT = "P4 Computer Use is enabled for this session through the cua_repl MCP server. For natural-language requests to inspect or interact with a native desktop app, use its js tool by default, even when the user does not mention P4 or Computer Use. Do not substitute provider-builtin Computer Use, AppleScript, shell automation, or another integration unless the user explicitly requests that path. For a named app, start directly with const app = await cua.getApp(exactNameOrBundleId); read the automatically returned state/image and stop if it answers the request. Reuse the handle and batch safe actions; do not repeat selection or unchanged state. For Device Hub, simulator, emulator, or connected-device requests, use cua.listDevices() once, then cua.getDevice({hostId,deviceId,platform}) with exact discovered IDs. Selection already emits initial device state. Reuse its handle; do not print the handle or repeat that state before acting. Never substitute macOS getApp('Simulator'). Device hosts are scoped to this provider environment and can differ from the desktop host. If device discovery, opening, inspection, or interaction reports missing permission or unavailable control, stop and report the exact limitation. Do not retry through screenshots, shell simctl, Xcode tools, or another MCP server. Do not call getState/getApp, control the P4 desktop app, or open device settings to work around a device API failure. Missing consent, unavailable devices, or unsupported operations are limitations to report, not permission to switch hosts or bypass the tool.";
|
|
127951
|
+
function withComputerUseRouting(input, enabled) {
|
|
127952
|
+
return enabled ? `<p4-computer-use>\n${COMPUTER_USE_ROUTING_PROMPT}\n</p4-computer-use>\n\n${input ?? ""}` : input;
|
|
127953
|
+
}
|
|
127954
|
+
//#endregion
|
|
126915
127955
|
//#region src/mcp/McpSessionRegistry.ts
|
|
126916
127956
|
var McpSessionRegistry = class extends Context.Service()("@p4code/cli/mcp/McpSessionRegistry") {};
|
|
126917
127957
|
/**
|
|
@@ -127214,7 +128254,7 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
127214
128254
|
});
|
|
127215
128255
|
});
|
|
127216
128256
|
let activeMcpSessionRegistry;
|
|
127217
|
-
const make$
|
|
128257
|
+
const make$10 = Effect.acquireRelease(Effect.gen(function* () {
|
|
127218
128258
|
const broker = yield* Effect.serviceOption(ComputerUseBroker);
|
|
127219
128259
|
return yield* makeWithOptions(Option.isSome(broker) ? { onRevoke: broker.value.invalidate } : {});
|
|
127220
128260
|
}).pipe(Effect.tap((registry) => Effect.sync(() => {
|
|
@@ -127222,7 +128262,7 @@ const make$9 = Effect.acquireRelease(Effect.gen(function* () {
|
|
|
127222
128262
|
}))), (registry) => registry.revokeAll.pipe(Effect.andThen(Effect.sync(() => {
|
|
127223
128263
|
if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
|
|
127224
128264
|
}))));
|
|
127225
|
-
const layer$
|
|
128265
|
+
const layer$6 = Layer.effect(McpSessionRegistry, make$10);
|
|
127226
128266
|
const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
|
|
127227
128267
|
/**
|
|
127228
128268
|
* Refreshes the liveness of a thread's MCP credential. Called on every provider
|
|
@@ -127685,7 +128725,10 @@ const makeProviderService = Effect.fn("makeProviderService")(function* (options)
|
|
|
127685
128725
|
...input.modelSelection?.model ? { "provider.model": input.modelSelection.model } : {}
|
|
127686
128726
|
});
|
|
127687
128727
|
yield* touchActiveMcpThread(input.threadId);
|
|
127688
|
-
const turn = yield* routed.adapter.sendTurn(
|
|
128728
|
+
const turn = yield* routed.adapter.sendTurn({
|
|
128729
|
+
...input,
|
|
128730
|
+
input: withComputerUseRouting(input.input, !forCompaction && Boolean(readMcpProviderSession(input.threadId)?.computerUse))
|
|
128731
|
+
});
|
|
127689
128732
|
yield* directory.upsert({
|
|
127690
128733
|
threadId: input.threadId,
|
|
127691
128734
|
provider: routed.adapter.provider,
|
|
@@ -128170,7 +129213,7 @@ const mcpToolkit = (toolkit) => Layer.effectDiscard(Effect.gen(function* () {
|
|
|
128170
129213
|
//#endregion
|
|
128171
129214
|
//#region src/mcp/toolkits/computerUse/tools.ts
|
|
128172
129215
|
const ComputerUseJsTool = Tool.make("js", {
|
|
128173
|
-
description: "Run JavaScript in a persistent
|
|
129216
|
+
description: "P4 Code Computer Use: control native apps through P4Code's signed helper. Run JavaScript in a persistent REPL. On the first call, execute exactly one entry-point operation and read its automatic output before continuing. When the user names an app, execute only const app = await cua.getApp(exactNameBundleIdOrPath); this already prints its state and includes a screenshot when AX exposes no app content. Use await cua.getState() only when discovery is needed. 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. Bindings disappear after helper restart, host disconnect, reset, or tray Stop. When resuming a task, guard a remembered binding within the same js call: if (typeof app === 'undefined') { globalThis.app = await cua.getApp('Spotify'); } else { await app.getScreenshot(); }. Substitute the named app and intended operation. The missing-binding branch selects only and prints fresh state; decide the next action after reading it. Never spend a separate tool call checking whether a binding exists. Reset after timeout or host disconnect. For available native apps, use cua.getApp(exactNameBundleIdOrPath), then getAXState(), click(elementIndex), or setValue(elementIndex,text) to replace a field value in the background. Selection already prints numbered accessibility state; reuse the app handle without selecting or reading it again before the first action. Snapshot text is bounded; use getAXState({filter:'Pause'}) for case-insensitive text filtering across the snapshot, including controls omitted from the initial output. Use {emit:false} on getApp(name, options), getAXState(options), or getScreenshot(options) when processing the returned value yourself; do not print auto-emitted output again. Several deterministic actions against distinct unchanged elements may share one snapshot. Each used element index expires after one action. To click the same control again, refresh with getAXState({filter: controlLabel}) first, even inside a batch; never reuse its old index. The host revalidates remaining native handles and rejects changed elements. Read fresh state after the action batch before deciding the next action. If selection includes a screenshot because AX exposes only window controls or menus, read that image immediately and finish if it answers the request. If no image is included, use getScreenshot() to read visual content; do not repeat unchanged snapshots hoping for missing accessibility content. 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 black pointer with a thin contrast edge 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. Selection automatically emits initial AX state (or a screenshot on other platforms); reuse the handle without repeating that capture or printing the handle. A permission or unavailable-control error requires stopping and reporting it, never shell or alternative-tool fallback. 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(). When getAXState() reports adapter apple-xcode or xcodebuildmcp, use semantic refs from capture.elements and only advertised capabilities: click(elementRef), typeText(text,{elementRef,replaceExisting:true}), swipe({withinElementRef,direction}), drag({elementRef,direction}), batch([{action:\"tap\",elementRef},...]), and recordVideo(\"start\"|\"stop\") only when advertised in capabilities. getAXState({sinceScreenHash}) avoids unchanged snapshots. Batch only same-screen taps; action output includes updated capture. On stale-ref errors inspect fresh state and choose a current ref; never replay an action automatically. Physical-device UI control and device key input are unavailable. 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.",
|
|
128174
129217
|
parameters: Schema$1.Struct({
|
|
128175
129218
|
...ComputerUseJsInput.fields,
|
|
128176
129219
|
hostId: Schema$1.optional(TrimmedNonEmptyString).annotate({ description: "Select an available host when more than one is connected. Reset before changing hosts." })
|
|
@@ -128629,7 +129672,7 @@ const stringField = (record, key) => {
|
|
|
128629
129672
|
const value = record[key];
|
|
128630
129673
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
128631
129674
|
};
|
|
128632
|
-
const make$
|
|
129675
|
+
const make$9 = Effect.gen(function* () {
|
|
128633
129676
|
const linear = yield* LinearClient;
|
|
128634
129677
|
return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
|
|
128635
129678
|
const identifier = parseTicketReference(reference);
|
|
@@ -128660,7 +129703,7 @@ const make$8 = Effect.gen(function* () {
|
|
|
128660
129703
|
};
|
|
128661
129704
|
}) };
|
|
128662
129705
|
});
|
|
128663
|
-
const layer$
|
|
129706
|
+
const layer$5 = Layer.effect(TicketResolver, make$9);
|
|
128664
129707
|
//#endregion
|
|
128665
129708
|
//#region src/mcp/toolkits/tasks/tools.ts
|
|
128666
129709
|
const dependencies = [McpInvocationContext, TaskRepository];
|
|
@@ -130001,6 +131044,34 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
130001
131044
|
})
|
|
130002
131045
|
});
|
|
130003
131046
|
//#endregion
|
|
131047
|
+
//#region src/orchestration/FusionBudgetPause.ts
|
|
131048
|
+
const pauseFusionBudget = Effect.fn("pauseFusionBudget")(function* (input) {
|
|
131049
|
+
const engine = yield* OrchestrationEngineService;
|
|
131050
|
+
const epoch = input.pair.reviewExperiment?.lastMessageSequence ?? 0;
|
|
131051
|
+
for (const threadId of [input.pair.implementerThreadId, input.pair.watcherThreadId]) {
|
|
131052
|
+
const id = `fusion-budget:${input.pair.id}:${epoch}:${threadId}`;
|
|
131053
|
+
yield* engine.dispatch({
|
|
131054
|
+
type: "thread.activity.append",
|
|
131055
|
+
commandId: CommandId.make(id),
|
|
131056
|
+
threadId,
|
|
131057
|
+
activity: {
|
|
131058
|
+
id: EventId.make(id),
|
|
131059
|
+
tone: "info",
|
|
131060
|
+
kind: "fusion.pair.paused",
|
|
131061
|
+
summary: `Fusion paused: ${input.reason}`,
|
|
131062
|
+
payload: {
|
|
131063
|
+
pairId: input.pair.id,
|
|
131064
|
+
reason: "review-budget",
|
|
131065
|
+
experiment: input.pair.reviewExperiment
|
|
131066
|
+
},
|
|
131067
|
+
turnId: null,
|
|
131068
|
+
createdAt: input.createdAt
|
|
131069
|
+
},
|
|
131070
|
+
createdAt: input.createdAt
|
|
131071
|
+
});
|
|
131072
|
+
}
|
|
131073
|
+
});
|
|
131074
|
+
//#endregion
|
|
130004
131075
|
//#region src/mcp/toolkits/advise/tools.ts
|
|
130005
131076
|
/**
|
|
130006
131077
|
* The write half of cross-thread access, and the reason advise is its own
|
|
@@ -130104,6 +131175,22 @@ const AdviseToolkitHandlersLive = AdviseToolkit.toLayer({
|
|
|
130104
131175
|
};
|
|
130105
131176
|
}
|
|
130106
131177
|
const createdAt = DateTime.formatIso(yield* DateTime.now);
|
|
131178
|
+
const activePair = readModel.threadPairs?.find((pair) => pair.detachedAt === null && pair.implementerThreadId === input.threadId);
|
|
131179
|
+
const budgetBlock = activePair && fusionBudgetBlock(activePair, input.threadId, `[fusion-advice] ${input.message}`);
|
|
131180
|
+
if (budgetBlock && activePair) {
|
|
131181
|
+
yield* pauseFusionBudget({
|
|
131182
|
+
pair: activePair,
|
|
131183
|
+
reason: budgetBlock,
|
|
131184
|
+
createdAt
|
|
131185
|
+
}).pipe(Effect.mapError((cause) => new ThreadAdviseFailedError({
|
|
131186
|
+
threadId: input.threadId,
|
|
131187
|
+
detail: cause.message
|
|
131188
|
+
})));
|
|
131189
|
+
return yield* new ThreadAdviseFailedError({
|
|
131190
|
+
threadId: input.threadId,
|
|
131191
|
+
detail: budgetBlock
|
|
131192
|
+
});
|
|
131193
|
+
}
|
|
130107
131194
|
const interrupted = input.interrupt === true;
|
|
130108
131195
|
if (interrupted) yield* dispatchAdvise({
|
|
130109
131196
|
type: "thread.turn.interrupt",
|
|
@@ -130391,7 +131478,7 @@ const ComputerUseMcpLive = ComputerUseToolkitRegistrationLive.pipe(Layer.provide
|
|
|
130391
131478
|
version: version$1,
|
|
130392
131479
|
path: "/mcp/computer-use"
|
|
130393
131480
|
}).pipe(Layer.provide(McpAuthMiddlewareLive))));
|
|
130394
|
-
const layer$
|
|
131481
|
+
const layer$4 = Layer.mergeAll(Layer.fresh(StandardMcpLive), Layer.fresh(ComputerUseMcpLive));
|
|
130395
131482
|
//#endregion
|
|
130396
131483
|
//#region src/hub/HubActivityTransport.ts
|
|
130397
131484
|
const REQUEST_TIMEOUT_MS = 8e3;
|
|
@@ -130681,7 +131768,7 @@ const runHubActivityEmission = Effect.fn("HubActivityRuntime.run")(function* (se
|
|
|
130681
131768
|
const outbound = yield* makeHubActivityOutbound(identity.destination);
|
|
130682
131769
|
yield* runHubActivityTick(outbound, transport, identity).pipe(Effect.tap(() => ready), Effect.repeat(Schedule.spaced(Duration.millis(HUB_ACTIVITY_INTERVAL_MS))));
|
|
130683
131770
|
});
|
|
130684
|
-
const layer$
|
|
131771
|
+
const layer$3 = Layer.effectDiscard(Effect.gen(function* () {
|
|
130685
131772
|
yield* runHubTunnelReconnect((yield* HubLink).changes, (settings, ready) => runHubActivityEmission(settings, ready).pipe(Effect.mapError((error) => error instanceof HubActivityUnauthorized ? new HubUnauthorizedError() : error))).pipe(Effect.forkScoped);
|
|
130686
131773
|
}));
|
|
130687
131774
|
//#endregion
|
|
@@ -131506,7 +132593,7 @@ const runHubTunnelOutbound = Effect.fn("HubTunnelOutbound.run")(function* (setti
|
|
|
131506
132593
|
yield* runHubTunnelPump(lease, socket, makeHubTunnelEnvironmentDispatch(localOrigin));
|
|
131507
132594
|
}));
|
|
131508
132595
|
});
|
|
131509
|
-
const layer$
|
|
132596
|
+
const layer$2 = Layer.effectDiscard(Effect.gen(function* () {
|
|
131510
132597
|
const link = yield* HubLink;
|
|
131511
132598
|
const server = yield* HttpServer.HttpServer;
|
|
131512
132599
|
if (server.address._tag !== "TcpAddress") return;
|
|
@@ -131578,7 +132665,7 @@ const COMPLETION_SWEEP_BATCH_SIZE = 25;
|
|
|
131578
132665
|
const COMPLETION_SWEEP_INTERVAL = Duration.minutes(1);
|
|
131579
132666
|
const COMPLETION_PR_TIMEOUT = Duration.seconds(10);
|
|
131580
132667
|
const MILLISECONDS_PER_DAY = 1440 * 60 * 1e3;
|
|
131581
|
-
const make$
|
|
132668
|
+
const make$8 = Effect.gen(function* () {
|
|
131582
132669
|
const sql = yield* SqlClient.SqlClient;
|
|
131583
132670
|
const settings = yield* ServerSettingsService;
|
|
131584
132671
|
const git = yield* GitManager;
|
|
@@ -131665,7 +132752,7 @@ const make$7 = Effect.gen(function* () {
|
|
|
131665
132752
|
};
|
|
131666
132753
|
});
|
|
131667
132754
|
var ThreadCompletionReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/ThreadCompletionReactor") {};
|
|
131668
|
-
const ThreadCompletionReactorLive = Layer.effect(ThreadCompletionReactor, make$
|
|
132755
|
+
const ThreadCompletionReactorLive = Layer.effect(ThreadCompletionReactor, make$8);
|
|
131669
132756
|
//#endregion
|
|
131670
132757
|
//#region src/orchestration/Services/ScheduledTaskReactor.ts
|
|
131671
132758
|
/**
|
|
@@ -131702,6 +132789,238 @@ const makeOrchestrationReactor = Effect.gen(function* () {
|
|
|
131702
132789
|
});
|
|
131703
132790
|
const OrchestrationReactorLive = Layer.effect(OrchestrationReactor, makeOrchestrationReactor);
|
|
131704
132791
|
//#endregion
|
|
132792
|
+
//#region src/usage/fusionObservation.ts
|
|
132793
|
+
const OBSERVATION_DAY_MS = 1440 * 60 * 1e3;
|
|
132794
|
+
const REVIEW_RATIO_THRESHOLD = .5;
|
|
132795
|
+
const REVIEW_COUNT_THRESHOLD = 10;
|
|
132796
|
+
const MILLISECONDS_PER_MINUTE = 60 * 1e3;
|
|
132797
|
+
function emptyRole() {
|
|
132798
|
+
return {
|
|
132799
|
+
turns: 0,
|
|
132800
|
+
failedTurns: 0,
|
|
132801
|
+
turnsWithUsage: 0,
|
|
132802
|
+
activeMinutes: 0,
|
|
132803
|
+
tokens: { ...EMPTY_TOTALS }
|
|
132804
|
+
};
|
|
132805
|
+
}
|
|
132806
|
+
function observationWeek(date) {
|
|
132807
|
+
const instant = DateTime.makeUnsafe(date);
|
|
132808
|
+
const daysSinceMonday = (DateTime.getPartUtc(instant, "weekDay") + 7 - 1) % 7;
|
|
132809
|
+
return DateTime.formatIso(DateTime.makeUnsafe(DateTime.toEpochMillis(instant) - daysSinceMonday * OBSERVATION_DAY_MS)).slice(0, 10);
|
|
132810
|
+
}
|
|
132811
|
+
/** Role consumption is descriptive; it cannot estimate a counterfactual solo run. */
|
|
132812
|
+
function buildFusionObservation(input) {
|
|
132813
|
+
const sinceMs = Date.parse(input.since);
|
|
132814
|
+
const untilMs = Date.parse(input.generatedAt);
|
|
132815
|
+
const pairs = /* @__PURE__ */ new Map();
|
|
132816
|
+
const sessions = /* @__PURE__ */ new Map();
|
|
132817
|
+
let missingSessionTurns = 0;
|
|
132818
|
+
for (const turn of input.turns) {
|
|
132819
|
+
const start = Math.max(sinceMs, Date.parse(turn.startedAt), Date.parse(turn.pairCreatedAt));
|
|
132820
|
+
const end = Math.min(untilMs, Date.parse(turn.completedAt), turn.detachedAt === null ? untilMs : Date.parse(turn.detachedAt));
|
|
132821
|
+
if (!Number.isFinite(start) || !Number.isFinite(end) || end < start) continue;
|
|
132822
|
+
let pair = pairs.get(turn.pairId);
|
|
132823
|
+
if (!pair) {
|
|
132824
|
+
pair = {
|
|
132825
|
+
pairId: turn.pairId,
|
|
132826
|
+
reviewPolicy: turn.reviewPolicy ?? null,
|
|
132827
|
+
builder: emptyRole(),
|
|
132828
|
+
review: emptyRole(),
|
|
132829
|
+
supervisorOther: emptyRole()
|
|
132830
|
+
};
|
|
132831
|
+
pairs.set(turn.pairId, pair);
|
|
132832
|
+
}
|
|
132833
|
+
const role = turn.role === "builder" ? pair.builder : turn.trigger === "review" || turn.trigger === "gate" ? pair.review : pair.supervisorOther;
|
|
132834
|
+
role.turns += 1;
|
|
132835
|
+
role.failedTurns += Number(turn.state !== "completed");
|
|
132836
|
+
role.activeMinutes += (end - start) / MILLISECONDS_PER_MINUTE;
|
|
132837
|
+
if (turn.sessionId === null) {
|
|
132838
|
+
missingSessionTurns += 1;
|
|
132839
|
+
continue;
|
|
132840
|
+
}
|
|
132841
|
+
const entries = sessions.get(turn.sessionId) ?? [];
|
|
132842
|
+
entries.push({
|
|
132843
|
+
start,
|
|
132844
|
+
end,
|
|
132845
|
+
role,
|
|
132846
|
+
observed: false
|
|
132847
|
+
});
|
|
132848
|
+
sessions.set(turn.sessionId, entries);
|
|
132849
|
+
}
|
|
132850
|
+
let unattributedRecords = 0;
|
|
132851
|
+
let ambiguousRecords = 0;
|
|
132852
|
+
const seen = /* @__PURE__ */ new Set();
|
|
132853
|
+
for (const record of input.records) {
|
|
132854
|
+
if (record.timestampMs < sinceMs || record.timestampMs > untilMs) continue;
|
|
132855
|
+
if (record.dedupeKey !== null) {
|
|
132856
|
+
if (seen.has(record.dedupeKey)) continue;
|
|
132857
|
+
seen.add(record.dedupeKey);
|
|
132858
|
+
}
|
|
132859
|
+
const matching = (sessions.get(record.sessionId) ?? []).filter((turn) => record.timestampMs >= turn.start && record.timestampMs <= turn.end);
|
|
132860
|
+
if (matching.length !== 1) {
|
|
132861
|
+
unattributedRecords += 1;
|
|
132862
|
+
if (matching.length > 1) ambiguousRecords += 1;
|
|
132863
|
+
continue;
|
|
132864
|
+
}
|
|
132865
|
+
const match = matching[0];
|
|
132866
|
+
match.role.tokens = addTotals(match.role.tokens, record.totals);
|
|
132867
|
+
if (!match.observed) match.role.turnsWithUsage += 1;
|
|
132868
|
+
match.observed = true;
|
|
132869
|
+
}
|
|
132870
|
+
const observedPairs = [...pairs.values()].map((pair) => {
|
|
132871
|
+
const builderTokens = totalTokens(pair.builder.tokens);
|
|
132872
|
+
const reviewTokens = totalTokens(pair.review.tokens);
|
|
132873
|
+
return {
|
|
132874
|
+
...pair,
|
|
132875
|
+
reviewTokensPerBuilderToken: builderTokens > 0 && reviewTokens > 0 ? reviewTokens / builderTokens : null
|
|
132876
|
+
};
|
|
132877
|
+
});
|
|
132878
|
+
const ratios = observedPairs.flatMap((pair) => pair.reviewTokensPerBuilderToken === null ? [] : [pair.reviewTokensPerBuilderToken]).sort((a, b) => a - b);
|
|
132879
|
+
const middle = Math.floor(ratios.length / 2);
|
|
132880
|
+
const median = ratios.length === 0 ? null : ratios.length % 2 === 0 ? (ratios[middle - 1] + ratios[middle]) / 2 : ratios[middle];
|
|
132881
|
+
const recommendations = [];
|
|
132882
|
+
const hasIncompleteUsage = missingSessionTurns > 0 || observedPairs.some((pair) => [
|
|
132883
|
+
pair.builder,
|
|
132884
|
+
pair.review,
|
|
132885
|
+
pair.supervisorOther
|
|
132886
|
+
].some((role) => role.turnsWithUsage < role.turns));
|
|
132887
|
+
if (hasIncompleteUsage) recommendations.push("Improve usage attribution before comparing policies; missing usage is not zero consumption.");
|
|
132888
|
+
if (ratios.length < 20) recommendations.push(`Collect at least 20 pairs with builder and review usage before selecting a policy experiment.`);
|
|
132889
|
+
else if (!hasIncompleteUsage && median !== null && median > REVIEW_RATIO_THRESHOLD) recommendations.push("Trial fewer review boundaries against the current policy on fixed tasks; compare independently verified outcomes and total cost.");
|
|
132890
|
+
if (observedPairs.some((pair) => pair.review.turns > REVIEW_COUNT_THRESHOLD)) recommendations.push(`Inspect pairs with more than ${REVIEW_COUNT_THRESHOLD} review turns for overly small phases or repeated corrections; a high count alone does not establish waste.`);
|
|
132891
|
+
recommendations.push("Keep settings unchanged until an isolated comparison passes acceptance and regression checks. These observations do not measure defects prevented or solo performance.");
|
|
132892
|
+
return {
|
|
132893
|
+
version: 1,
|
|
132894
|
+
mode: "observe",
|
|
132895
|
+
generatedAt: input.generatedAt,
|
|
132896
|
+
since: input.since,
|
|
132897
|
+
timeZone: "UTC",
|
|
132898
|
+
coverage: {
|
|
132899
|
+
pairs: observedPairs.length,
|
|
132900
|
+
pairsWithBothUsage: ratios.length,
|
|
132901
|
+
missingSessionTurns,
|
|
132902
|
+
unattributedRecords,
|
|
132903
|
+
ambiguousRecords
|
|
132904
|
+
},
|
|
132905
|
+
medianReviewTokensPerBuilderToken: median,
|
|
132906
|
+
limitations: [
|
|
132907
|
+
"Only completed or failed turn intervals are counted; ongoing turns are excluded.",
|
|
132908
|
+
"Current session linkage may omit usage before a provider session reset; unsupported providers remain unmeasured.",
|
|
132909
|
+
"Codex subagent sessions are not linked; Claude descendants sharing the parent session id can be included.",
|
|
132910
|
+
"Cached tokens are included. Tokens and wall time are not billing, quota, latency overhead, or causal quality measurements.",
|
|
132911
|
+
"Supervisor startup and direct user turns are separate from automatic reviews; review-induced builder repairs are not separable."
|
|
132912
|
+
],
|
|
132913
|
+
pairs: observedPairs,
|
|
132914
|
+
recommendations
|
|
132915
|
+
};
|
|
132916
|
+
}
|
|
132917
|
+
//#endregion
|
|
132918
|
+
//#region src/usage/FusionObservationService.ts
|
|
132919
|
+
const OBSERVATION_CHECK_INTERVAL = Duration.hours(1);
|
|
132920
|
+
const ReportStamp = Schema$1.Struct({
|
|
132921
|
+
version: Schema$1.Literal(1),
|
|
132922
|
+
generatedAt: Schema$1.String
|
|
132923
|
+
});
|
|
132924
|
+
const TurnRow = Schema$1.Struct({
|
|
132925
|
+
pairId: Schema$1.String,
|
|
132926
|
+
reviewPolicy: Schema$1.NullOr(Schema$1.fromJsonString(FusionReviewPolicy)),
|
|
132927
|
+
threadId: Schema$1.String,
|
|
132928
|
+
turnId: Schema$1.String,
|
|
132929
|
+
role: Schema$1.Literals(["builder", "supervisor"]),
|
|
132930
|
+
sessionId: Schema$1.NullOr(Schema$1.String),
|
|
132931
|
+
pairCreatedAt: Schema$1.String,
|
|
132932
|
+
detachedAt: Schema$1.NullOr(Schema$1.String),
|
|
132933
|
+
startedAt: Schema$1.String,
|
|
132934
|
+
completedAt: Schema$1.String,
|
|
132935
|
+
state: Schema$1.String,
|
|
132936
|
+
trigger: Schema$1.Literals([
|
|
132937
|
+
"review",
|
|
132938
|
+
"gate",
|
|
132939
|
+
"advice",
|
|
132940
|
+
"other"
|
|
132941
|
+
])
|
|
132942
|
+
});
|
|
132943
|
+
const decodeReportStamp = Schema$1.decodeUnknownEffect(Schema$1.fromJsonString(ReportStamp));
|
|
132944
|
+
const decodeTurns = Schema$1.decodeUnknownEffect(Schema$1.Array(TurnRow));
|
|
132945
|
+
const encodeReport = Schema$1.encodeEffect(Schema$1.UnknownFromJsonString);
|
|
132946
|
+
/** Reads existing projections only; observation never dispatches orchestration commands. */
|
|
132947
|
+
const make$7 = Effect.gen(function* () {
|
|
132948
|
+
const sql = yield* SqlClient.SqlClient;
|
|
132949
|
+
const fs = yield* FileSystem.FileSystem;
|
|
132950
|
+
const path = yield* Path$1.Path;
|
|
132951
|
+
const config = yield* ServerConfig$1;
|
|
132952
|
+
const settings = yield* ServerSettingsService;
|
|
132953
|
+
const usage = yield* UsageService;
|
|
132954
|
+
const lock = yield* Semaphore.make(1);
|
|
132955
|
+
const directory = path.join(config.stateDir, "fusion-observation");
|
|
132956
|
+
const latestPath = path.join(directory, "latest.json");
|
|
132957
|
+
const writeReport = Effect.fn("FusionObservation.writeReport")(function* (destination, body) {
|
|
132958
|
+
const temporary = `${destination}.tmp`;
|
|
132959
|
+
yield* fs.writeFileString(temporary, body);
|
|
132960
|
+
yield* fs.rename(temporary, destination);
|
|
132961
|
+
});
|
|
132962
|
+
const refresh = Effect.fn("FusionObservation.refresh")(function* () {
|
|
132963
|
+
if (!(yield* settings.getSettings).enableFusionObservation) return;
|
|
132964
|
+
const now = yield* Clock.currentTimeMillis;
|
|
132965
|
+
const generatedAt = DateTime.formatIso(DateTime.makeUnsafe(now));
|
|
132966
|
+
const weeklyPath = path.join(directory, `week-${observationWeek(generatedAt)}.json`);
|
|
132967
|
+
const stamp = yield* fs.readFileString(latestPath).pipe(Effect.flatMap(decodeReportStamp), Effect.orElseSucceed(() => null));
|
|
132968
|
+
const weeklyExists = yield* fs.exists(weeklyPath);
|
|
132969
|
+
if (stamp?.generatedAt.slice(0, 10) === generatedAt.slice(0, 10) && weeklyExists) return;
|
|
132970
|
+
const since = DateTime.formatIso(DateTime.makeUnsafe(now - 7 * OBSERVATION_DAY_MS));
|
|
132971
|
+
const rows = yield* sql`
|
|
132972
|
+
SELECT p.pair_id AS "pairId", t.thread_id AS "threadId", t.turn_id AS "turnId",
|
|
132973
|
+
CASE WHEN t.thread_id = p.implementer_thread_id THEN 'builder' ELSE 'supervisor' END AS role,
|
|
132974
|
+
CASE WHEN json_valid(r.resume_cursor_json) THEN
|
|
132975
|
+
CASE WHEN r.provider_name = 'codex' THEN json_extract(r.resume_cursor_json, '$.threadId')
|
|
132976
|
+
WHEN r.provider_name = 'claudeAgent' THEN json_extract(r.resume_cursor_json, '$.resume') END
|
|
132977
|
+
END AS "sessionId",
|
|
132978
|
+
json_extract(p.review_experiment_json, '$.policy') AS "reviewPolicy",
|
|
132979
|
+
p.created_at AS "pairCreatedAt", p.detached_at AS "detachedAt",
|
|
132980
|
+
coalesce(t.started_at, t.requested_at) AS "startedAt", t.completed_at AS "completedAt", t.state,
|
|
132981
|
+
CASE WHEN substr(m.text, 1, 15) = '[fusion-review]' THEN 'review'
|
|
132982
|
+
WHEN substr(m.text, 1, 13) = '[fusion-gate]' THEN 'gate'
|
|
132983
|
+
WHEN substr(m.text, 1, 15) = '[fusion-advice]' THEN 'advice' ELSE 'other' END AS trigger
|
|
132984
|
+
FROM thread_pairs p
|
|
132985
|
+
JOIN projection_turns t ON t.thread_id IN (p.implementer_thread_id, p.watcher_thread_id)
|
|
132986
|
+
LEFT JOIN provider_session_runtime r ON r.thread_id = t.thread_id
|
|
132987
|
+
LEFT JOIN projection_thread_messages m ON m.message_id = t.pending_message_id
|
|
132988
|
+
WHERE t.turn_id IS NOT NULL AND t.completed_at >= ${since} AND t.completed_at <= ${generatedAt}
|
|
132989
|
+
AND t.completed_at >= p.created_at
|
|
132990
|
+
AND (p.detached_at IS NULL OR t.requested_at <= p.detached_at)
|
|
132991
|
+
`;
|
|
132992
|
+
const turns = yield* decodeTurns(rows);
|
|
132993
|
+
const sessionIds = [...new Set(turns.flatMap((turn) => turn.sessionId === null ? [] : [turn.sessionId]))];
|
|
132994
|
+
const report = buildFusionObservation({
|
|
132995
|
+
generatedAt,
|
|
132996
|
+
since,
|
|
132997
|
+
turns,
|
|
132998
|
+
records: yield* usage.readSessionRecords({
|
|
132999
|
+
sessionIds,
|
|
133000
|
+
sinceMs: Date.parse(since)
|
|
133001
|
+
})
|
|
133002
|
+
});
|
|
133003
|
+
yield* fs.makeDirectory(directory, { recursive: true });
|
|
133004
|
+
const body = yield* encodeReport(report);
|
|
133005
|
+
if (!weeklyExists) {
|
|
133006
|
+
yield* writeReport(weeklyPath, body);
|
|
133007
|
+
yield* Effect.logInfo("Weekly Fusion observation available", {
|
|
133008
|
+
path: weeklyPath,
|
|
133009
|
+
pairs: report.coverage.pairs
|
|
133010
|
+
});
|
|
133011
|
+
}
|
|
133012
|
+
yield* writeReport(latestPath, body);
|
|
133013
|
+
});
|
|
133014
|
+
const run = lock.withPermits(1)(refresh());
|
|
133015
|
+
return {
|
|
133016
|
+
refresh: run,
|
|
133017
|
+
start: run.pipe(Effect.catchCause((cause) => Cause.hasInterruptsOnly(cause) ? Effect.failCause(cause) : Effect.logWarning("Fusion observation failed; retrying on the next scheduled check")), Effect.repeat(Schedule.spaced(OBSERVATION_CHECK_INTERVAL)), Effect.forkScoped)
|
|
133018
|
+
};
|
|
133019
|
+
});
|
|
133020
|
+
const layer$1 = Layer.effectDiscard(Effect.gen(function* () {
|
|
133021
|
+
yield* (yield* make$7).start;
|
|
133022
|
+
}));
|
|
133023
|
+
//#endregion
|
|
131705
133024
|
//#region src/orchestration/Services/RuntimeReceiptBus.ts
|
|
131706
133025
|
/**
|
|
131707
133026
|
* RuntimeReceiptBus - Internal checkpoint-reactor synchronization receipts.
|
|
@@ -132158,6 +133477,7 @@ function runtimeEventToActivities(event, taskTitle, compressMode) {
|
|
|
132158
133477
|
summary: event.payload.description.trim().length > 0 ? truncateDetail(event.payload.description, 120) : "Reasoning update",
|
|
132159
133478
|
payload: {
|
|
132160
133479
|
taskId: event.payload.taskId,
|
|
133480
|
+
...event.payload.model ? { model: event.payload.model } : {},
|
|
132161
133481
|
...event.provider === "claudeAgent" && event.payload.workflowScript?.instanceId === event.providerInstanceId ? { workflowScript: event.payload.workflowScript } : {},
|
|
132162
133482
|
...event.payload.description.trim().length > 0 ? { title: truncateDetail(event.payload.description, 120) } : {},
|
|
132163
133483
|
detail: event.payload.summary ?? event.payload.description,
|
|
@@ -132919,7 +134239,7 @@ const make$6 = Effect.gen(function* () {
|
|
|
132919
134239
|
drain: worker.drain
|
|
132920
134240
|
};
|
|
132921
134241
|
});
|
|
132922
|
-
const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$6).pipe(Layer.provide(ProjectionTurnRepositoryLive), Layer.provide(layer$
|
|
134242
|
+
const ProviderRuntimeIngestionLive = Layer.effect(ProviderRuntimeIngestionService, make$6).pipe(Layer.provide(ProjectionTurnRepositoryLive), Layer.provide(layer$83));
|
|
132923
134243
|
//#endregion
|
|
132924
134244
|
//#region src/provider/userInvokedSkills.ts
|
|
132925
134245
|
/**
|
|
@@ -133759,6 +135079,7 @@ const make$5 = Effect.gen(function* () {
|
|
|
133759
135079
|
].join("\n\n") : fusionRole === "watcher" && isFusionWatcherWakeMessageId(input.messageId) ? sidechatSeededInput : [
|
|
133760
135080
|
sessionFusionRole === fusionRole ? fusionRoleReferenceLineFor(fusionRole) : fusionRoleInstructionsFor(fusionRole),
|
|
133761
135081
|
fusionPairContext(activeFusionPair, fusionRole),
|
|
135082
|
+
fusionReviewPolicyInstructions(activeFusionPair.reviewExperiment),
|
|
133762
135083
|
sidechatSeededInput
|
|
133763
135084
|
].join("\n\n");
|
|
133764
135085
|
const providerHasStructuredQuestionSystemPrompt = activeSession?.provider === "claudeAgent" || activeSession?.provider === "codex";
|
|
@@ -134841,7 +136162,7 @@ Then thread_gate_respond, threadId ${input.implementerThreadId}, gateId ${input.
|
|
|
134841
136162
|
- "approve": clear gate, continue builder.
|
|
134842
136163
|
- "object" plus message: send objection, spend round. After ${input.roundCap} objections, escalate to user.
|
|
134843
136164
|
|
|
134844
|
-
No answer within ${Math.round(input.gateTimeoutMs / 1e3)} seconds: fail open, record unwatched. Answer, briefly explain to user, end turn; never wait for builder.`;
|
|
136165
|
+
No answer within ${Math.round(input.gateTimeoutMs / 1e3)} seconds: ${input.failClosed ? "escalate to the user; keep work unapproved" : "fail open, record unwatched"}. Answer, briefly explain to user, end turn; never wait for builder.`;
|
|
134845
136166
|
const make$3 = Effect.gen(function* () {
|
|
134846
136167
|
const orchestrationEngine = yield* OrchestrationEngineService;
|
|
134847
136168
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
@@ -134944,6 +136265,9 @@ const make$3 = Effect.gen(function* () {
|
|
|
134944
136265
|
discard: true
|
|
134945
136266
|
});
|
|
134946
136267
|
});
|
|
136268
|
+
const wakeWasRequested = Effect.fn("FusionWatcherReactor.wakeWasRequested")(function* (afterSequence, throughSequence, messageId) {
|
|
136269
|
+
return (yield* orchestrationEngine.readEvents(afterSequence, throughSequence - afterSequence, { eventTypes: ["thread.turn-start-requested"] }).pipe(Stream.takeWhile((event) => event.sequence <= throughSequence), Stream.filter((event) => event.type === "thread.turn-start-requested" && event.payload.messageId === messageId), Stream.take(1), Stream.runCollect)).length > 0;
|
|
136270
|
+
});
|
|
134947
136271
|
/** Starts one watcher turn for the open gate and advances the pair cursor. */
|
|
134948
136272
|
const wakeWatcherForGate = Effect.fn("FusionWatcherReactor.wakeWatcherForGate")(function* (event) {
|
|
134949
136273
|
const gate = event.payload.gate;
|
|
@@ -134951,8 +136275,26 @@ const make$3 = Effect.gen(function* () {
|
|
|
134951
136275
|
const { readModel, activePairs } = yield* readPairs;
|
|
134952
136276
|
const pair = activePairs.find((candidate) => candidate.id === event.payload.pairId);
|
|
134953
136277
|
if (pair === void 0) return;
|
|
136278
|
+
if (pair.reviewExperiment && (pair.activeGate?.id !== gate.id || pair.activeGate.state !== "awaiting-watcher" || pair.activeGate.round !== gate.round)) return;
|
|
134954
136279
|
const watcher = readModel.threads.find((thread) => thread.id === pair.watcherThreadId && thread.deletedAt === null);
|
|
134955
136280
|
if (watcher === void 0) return;
|
|
136281
|
+
const budgetBlock = fusionBudgetBlock(pair, watcher.id, FUSION_GATE_PROMPT_PREFIX);
|
|
136282
|
+
if (budgetBlock && !(yield* wakeWasRequested(event.sequence, readModel.snapshotSequence, gateMessageId(gate.id, gate.round)))) {
|
|
136283
|
+
yield* orchestrationEngine.dispatch({
|
|
136284
|
+
type: "thread-pair.gate.advance",
|
|
136285
|
+
commandId: gateCommandId(pair.id, gate.id, `budget:${gate.round}`),
|
|
136286
|
+
pairId: pair.id,
|
|
136287
|
+
gateId: gate.id,
|
|
136288
|
+
transition: "escalate",
|
|
136289
|
+
advancedAt: gate.updatedAt
|
|
136290
|
+
});
|
|
136291
|
+
yield* pauseFusionBudget({
|
|
136292
|
+
pair,
|
|
136293
|
+
reason: budgetBlock,
|
|
136294
|
+
createdAt: gate.updatedAt
|
|
136295
|
+
});
|
|
136296
|
+
return;
|
|
136297
|
+
}
|
|
134956
136298
|
yield* orchestrationEngine.dispatch({
|
|
134957
136299
|
type: "thread.turn.start",
|
|
134958
136300
|
commandId: gateCommandId(pair.id, gate.id, `wake:${gate.round}`),
|
|
@@ -134965,9 +136307,10 @@ const make$3 = Effect.gen(function* () {
|
|
|
134965
136307
|
gate,
|
|
134966
136308
|
roundCap: pair.roundCap,
|
|
134967
136309
|
gateTimeoutMs: pair.gateTimeoutMs,
|
|
136310
|
+
failClosed: pair.reviewExperiment != null,
|
|
134968
136311
|
afterSequence: pair.lastReviewedImplementerSequence,
|
|
134969
136312
|
throughSequence: event.sequence
|
|
134970
|
-
}),
|
|
136313
|
+
}) + "\n\n" + fusionReviewPolicyInstructions(pair.reviewExperiment),
|
|
134971
136314
|
attachments: []
|
|
134972
136315
|
},
|
|
134973
136316
|
runtimeMode: watcher.runtimeMode,
|
|
@@ -135301,6 +136644,15 @@ const make$3 = Effect.gen(function* () {
|
|
|
135301
136644
|
implementerSequence: completion.sequence,
|
|
135302
136645
|
advancedAt: completion.occurredAt
|
|
135303
136646
|
});
|
|
136647
|
+
const budgetBlock = fusionBudgetBlock(currentPair, watcher.id, FUSION_REVIEW_PROMPT_PREFIX);
|
|
136648
|
+
if (budgetBlock && !(yield* wakeWasRequested(completion.sequence, readModel.snapshotSequence, reviewMessageId(currentPair.id, completion.sequence)))) {
|
|
136649
|
+
yield* pauseFusionBudget({
|
|
136650
|
+
pair: currentPair,
|
|
136651
|
+
reason: budgetBlock,
|
|
136652
|
+
createdAt: completion.occurredAt
|
|
136653
|
+
});
|
|
136654
|
+
return;
|
|
136655
|
+
}
|
|
135304
136656
|
const idleCycles = turn.startedByAdvice && !turn.humanMessage && !turn.ranTools ? (idleAdviceCycles.get(currentPair.id) ?? 0) + 1 : 0;
|
|
135305
136657
|
idleAdviceCycles.set(currentPair.id, idleCycles);
|
|
135306
136658
|
if (idleCycles >= 3) {
|
|
@@ -135324,7 +136676,7 @@ const make$3 = Effect.gen(function* () {
|
|
|
135324
136676
|
implementerThreadId: currentPair.implementerThreadId,
|
|
135325
136677
|
afterSequence: currentPair.lastReviewedImplementerSequence,
|
|
135326
136678
|
throughSequence: completion.sequence
|
|
135327
|
-
}),
|
|
136679
|
+
}) + "\n\n" + fusionReviewPolicyInstructions(currentPair.reviewExperiment),
|
|
135328
136680
|
attachments: []
|
|
135329
136681
|
},
|
|
135330
136682
|
runtimeMode: watcher.runtimeMode,
|
|
@@ -135378,6 +136730,7 @@ const make$3 = Effect.gen(function* () {
|
|
|
135378
136730
|
});
|
|
135379
136731
|
completions = completions.filter((completion) => completion !== activationCompletion);
|
|
135380
136732
|
}
|
|
136733
|
+
if (pair.reviewExperiment) completions = completions.filter((completion) => completion.payload.state === "completed").slice(-1);
|
|
135381
136734
|
let boundary = activationCompletion?.sequence ?? pair.lastReviewedImplementerSequence;
|
|
135382
136735
|
for (const completion of completions.filter((candidate) => candidate.payload.state === "completed")) {
|
|
135383
136736
|
const turn = describeBuilderTurn({
|
|
@@ -135425,6 +136778,17 @@ const make$3 = Effect.gen(function* () {
|
|
|
135425
136778
|
if (gate.awaitingWatcherSince === null) continue;
|
|
135426
136779
|
const since = Date.parse(gate.awaitingWatcherSince);
|
|
135427
136780
|
if (Number.isNaN(since) || nowMillis - since < pair.gateTimeoutMs) continue;
|
|
136781
|
+
if (pair.reviewExperiment) {
|
|
136782
|
+
yield* orchestrationEngine.dispatch({
|
|
136783
|
+
type: "thread-pair.gate.advance",
|
|
136784
|
+
commandId: gateCommandId(pair.id, gate.id, `timeout-escalate:${gate.round}`),
|
|
136785
|
+
pairId: pair.id,
|
|
136786
|
+
gateId: gate.id,
|
|
136787
|
+
transition: "escalate",
|
|
136788
|
+
advancedAt: DateTime.formatIso(now)
|
|
136789
|
+
});
|
|
136790
|
+
continue;
|
|
136791
|
+
}
|
|
135428
136792
|
yield* orchestrationEngine.dispatch({
|
|
135429
136793
|
type: "thread-pair.gate.resolve",
|
|
135430
136794
|
commandId: gateCommandId(pair.id, gate.id, `timeout:${gate.round}`),
|
|
@@ -136441,7 +137805,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
136441
137805
|
sink,
|
|
136442
137806
|
...delegate ? { delegate } : {}
|
|
136443
137807
|
});
|
|
136444
|
-
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$
|
|
137808
|
+
return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$62(sink));
|
|
136445
137809
|
})).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
|
|
136446
137810
|
const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
|
|
136447
137811
|
url: config.otlpMetricsUrl,
|
|
@@ -136813,31 +138177,31 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
136813
138177
|
}
|
|
136814
138178
|
}));
|
|
136815
138179
|
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));
|
|
136816
|
-
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$
|
|
138180
|
+
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$7));
|
|
136817
138181
|
const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
|
|
136818
138182
|
const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
|
|
136819
|
-
const VcsDriverRegistryLayerLive = layer$
|
|
136820
|
-
const SourceControlProviderRegistryLayerLive = layer$
|
|
136821
|
-
const GitManagerLayerLive = layer$
|
|
136822
|
-
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$
|
|
136823
|
-
const GitWorkflowLayerLive = layer$
|
|
136824
|
-
const SourceControlRepositoryServiceLayerLive = layer$
|
|
136825
|
-
const ReviewLayerLive = layer$
|
|
136826
|
-
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
136827
|
-
const PullRequestServiceLive = layer$
|
|
136828
|
-
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
136829
|
-
const PortScannerLayerLive = layer$
|
|
136830
|
-
const TerminalLayerLive = layer$
|
|
136831
|
-
const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$
|
|
136832
|
-
const WorkspaceEntriesLayerLive = layer$
|
|
136833
|
-
const WorkspaceFileSystemLayerLive = layer$
|
|
138183
|
+
const VcsDriverRegistryLayerLive = layer$48.pipe(Layer.provide(layer$49));
|
|
138184
|
+
const SourceControlProviderRegistryLayerLive = layer$34.pipe(Layer.provide(Layer.mergeAll(layer$42, layer$40, layer$38, layer$36)), Layer.provideMerge(layer$50), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
138185
|
+
const GitManagerLayerLive = layer$33.pipe(Layer.provideMerge(layer$43), Layer.provideMerge(layer$50), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$59));
|
|
138186
|
+
const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$50));
|
|
138187
|
+
const GitWorkflowLayerLive = layer$32.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
|
|
138188
|
+
const SourceControlRepositoryServiceLayerLive = layer$8.pipe(Layer.provideMerge(layer$50), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
|
|
138189
|
+
const ReviewLayerLive = layer$13.pipe(Layer.provideMerge(layer$50), Layer.provideMerge(VcsDriverRegistryLayerLive));
|
|
138190
|
+
const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$49), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$14.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$15.pipe(Layer.provide(autoPullPolicyLayer), Layer.provide(GitWorkflowLayerLive))));
|
|
138191
|
+
const PullRequestServiceLive = layer$26.pipe(Layer.provide(layer$27), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(layer$51));
|
|
138192
|
+
const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$46), Layer.provideMerge(layer$47.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
|
|
138193
|
+
const PortScannerLayerLive = layer$45.pipe(Layer.provide(layer$82));
|
|
138194
|
+
const TerminalLayerLive = layer$44.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
|
|
138195
|
+
const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$19), Layer.provideMerge(PortScannerLayerLive));
|
|
138196
|
+
const WorkspaceEntriesLayerLive = layer$17.pipe(Layer.provide(layer$68));
|
|
138197
|
+
const WorkspaceFileSystemLayerLive = layer$16.pipe(Layer.provide(layer$68), Layer.provide(WorkspaceEntriesLayerLive));
|
|
136834
138198
|
const WorkspaceLayerLive = Layer.mergeAll(layer$68, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
|
|
136835
|
-
const ProjectFaviconResolverLayerLive = layer$
|
|
136836
|
-
const AuthLayerLive = layer$
|
|
138199
|
+
const ProjectFaviconResolverLayerLive = layer$63.pipe(Layer.provide(layer$68), Layer.provide(layer$64));
|
|
138200
|
+
const AuthLayerLive = layer$111.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$115));
|
|
136837
138201
|
const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
|
|
136838
|
-
const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$
|
|
136839
|
-
const UsageLayerLive = layer$
|
|
136840
|
-
const RuntimeDependenciesLive = layer$
|
|
138202
|
+
const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(layer$25), 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$86)), Layer.provideMerge(layer$80), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(layer$58), Layer.provideMerge(Layer.mergeAll(layer$57, layer$70.pipe(Layer.provide(layer$82)), layer$72, layer$67)), Layer.provideMerge(layer$52), Layer.provideMerge(layer$53), Layer.provideMerge(layer$54), Layer.provideMerge(layer$55), Layer.provideMerge(layer$56)).pipe(Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(AntigravityInstallation.layer), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$60), Layer.provideMerge(layer$90.pipe(Layer.provide(layer$115))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$81), Layer.provideMerge(layer$66), Layer.provideMerge(remoteComputerUseBindingsLayer.pipe(Layer.provide(layer$86))), Layer.provideMerge(layer$74), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$5.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$87, layer$21).pipe(Layer.provideMerge(layer$88), Layer.provideMerge(layer$89))))), Layer.provideMerge(layer$115));
|
|
138203
|
+
const UsageLayerLive = layer$23.pipe(Layer.provide(layer$90.pipe(Layer.provide(layer$115))));
|
|
138204
|
+
const RuntimeDependenciesLive = layer$22.pipe(Layer.provideMerge(RuntimeCoreDependenciesLive)).pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$12), Layer.provideMerge(layer$11), Layer.provideMerge(layer$10), Layer.provideMerge(layer$77), Layer.provideMerge(layer$79), Layer.provideMerge(layer$78), Layer.provide(layer$119));
|
|
136841
138205
|
/**
|
|
136842
138206
|
* Hub asset sync.
|
|
136843
138207
|
*
|
|
@@ -136845,9 +138209,9 @@ const RuntimeDependenciesLive = layer$21.pipe(Layer.provideMerge(RuntimeCoreDepe
|
|
|
136845
138209
|
* not-configured shape, and every call reports that rather than failing — so
|
|
136846
138210
|
* this costs a server with no hub nothing but a layer.
|
|
136847
138211
|
*/
|
|
136848
|
-
const AssetSyncLive = layer$
|
|
136849
|
-
const RuntimeServicesLive = layer$69.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
|
|
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$
|
|
138212
|
+
const AssetSyncLive = layer$84.pipe(Layer.provideMerge(layer$85), Layer.provideMerge(layer$86));
|
|
138213
|
+
const RuntimeServicesLive = layer$69.pipe(Layer.provideMerge(layer$1), Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
|
|
138214
|
+
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$4.pipe(Layer.provide(layer$6)), layer$65, layer).pipe(Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(ProjectionThreadRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$64), Layer.provide(layer$25), Layer.provide(PullRequestServiceLive), Layer.provide(layer$20), Layer.provide(layer$75), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
|
|
136851
138215
|
const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
136852
138216
|
const config = yield* ServerConfig$1;
|
|
136853
138217
|
yield* fixPath();
|
|
@@ -136890,7 +138254,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
|
|
|
136890
138254
|
cause,
|
|
136891
138255
|
servePort: configured.servePort
|
|
136892
138256
|
}))) : Effect.void)) : Layer.empty;
|
|
136893
|
-
const fullyProvisionedServerLayer = Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer, layer$
|
|
138257
|
+
const fullyProvisionedServerLayer = Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer, layer$2, layer$3).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$51));
|
|
136894
138258
|
return Layer.unwrap(Effect.gen(function* () {
|
|
136895
138259
|
yield* acquireServerInstanceLock(config.stateDir);
|
|
136896
138260
|
return fullyProvisionedServerLayer;
|
|
@@ -137192,11 +138556,11 @@ function describeServiceUpdateState(state) {
|
|
|
137192
138556
|
//#endregion
|
|
137193
138557
|
//#region src/cli/service.ts
|
|
137194
138558
|
const isBootServiceCommandError = Schema$1.is(BootServiceCommandError);
|
|
137195
|
-
const bootServiceLayer = (config) => layer$
|
|
138559
|
+
const bootServiceLayer = (config) => layer$76({
|
|
137196
138560
|
baseDir: config.baseDir,
|
|
137197
138561
|
logsDir: config.logsDir,
|
|
137198
138562
|
cliVersion: version$1
|
|
137199
|
-
}).pipe(Layer.provide(layer$
|
|
138563
|
+
}).pipe(Layer.provide(layer$82));
|
|
137200
138564
|
/**
|
|
137201
138565
|
* The update installed a build that never reported itself listening.
|
|
137202
138566
|
*
|
|
@@ -137322,7 +138686,7 @@ const runServiceCommand = Effect.fn("cli.service.run")(function* (flags, run, pr
|
|
|
137322
138686
|
const baseDirNotice = yield* describeNonDefaultBaseDir(config.baseDir);
|
|
137323
138687
|
if (baseDirNotice !== null) yield* Console.error(baseDirNotice);
|
|
137324
138688
|
if (prepare !== void 0) yield* prepare(config);
|
|
137325
|
-
return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$
|
|
138689
|
+
return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$82)));
|
|
137326
138690
|
});
|
|
137327
138691
|
/**
|
|
137328
138692
|
* Options the installed unit carries, rather than ones this command consumes.
|
|
@@ -137489,7 +138853,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
|
|
|
137489
138853
|
]));
|
|
137490
138854
|
//#endregion
|
|
137491
138855
|
//#region src/bin.ts
|
|
137492
|
-
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$
|
|
138856
|
+
const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$119, FetchHttpClient.layer);
|
|
137493
138857
|
/**
|
|
137494
138858
|
* Prints an update reminder before dispatching, at most once a day.
|
|
137495
138859
|
*
|