@p4code/cli 0.4.7 → 0.4.9
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 +1564 -432
- package/dist/client/assets/DiffPanel-ycRv5wGO.js +98 -0
- package/dist/client/assets/{FilePreviewPanel-C4mhcqUa.js → FilePreviewPanel-CSGuz1fr.js} +12 -12
- package/dist/client/assets/PreviewPanel-CjVVqlpK.js +2 -0
- package/dist/client/assets/PullRequestCodeTab-DLNChos3.js +251 -0
- package/dist/client/assets/{fileCommentAnnotations-Cj4zw1MU.js → fileCommentAnnotations-CfmoUfij.js} +2 -2
- package/dist/client/assets/index-BMtTA7Do.js +2765 -0
- package/dist/client/assets/{index-BCNkRAfG.css → index-CGz5G9YO.css} +1 -1
- package/dist/client/assets/previewAssetResource-DoQeyCSk.js +48 -0
- package/dist/client/assets/{renderFileChildren-BAjW_l4M.js → renderFileChildren-UOFwKVtT.js} +2 -2
- package/dist/client/assets/toggle-group-CV9ZqEQ_.js +2 -0
- package/dist/client/index.html +3 -3
- package/package.json +1 -1
- package/dist/client/assets/DiffPanel-Bha2NDZW.js +0 -98
- package/dist/client/assets/PreviewPanel-bDoNhUkw.js +0 -2
- package/dist/client/assets/PullRequestCodeTab-DA0giwjP.js +0 -251
- package/dist/client/assets/index-Bph2wD2H.js +0 -2747
- package/dist/client/assets/previewAssetResource-BSwDMX3X.js +0 -48
- package/dist/client/assets/toggle-group-D9sObSNY.js +0 -2
package/dist/bin.mjs
CHANGED
|
@@ -52,6 +52,7 @@ import * as SqlClient from "effect/unstable/sql/SqlClient";
|
|
|
52
52
|
import * as SqlSchema from "effect/unstable/sql/SqlSchema";
|
|
53
53
|
import * as PlatformError from "effect/PlatformError";
|
|
54
54
|
import * as Migrator from "effect/unstable/sql/Migrator";
|
|
55
|
+
import * as NodeUtil from "node:util";
|
|
55
56
|
import * as Cause from "effect/Cause";
|
|
56
57
|
import * as Exit from "effect/Exit";
|
|
57
58
|
import * as NodeReadline from "node:readline";
|
|
@@ -127,7 +128,7 @@ const closeServer = (server) => {
|
|
|
127
128
|
* NetService - Service tag for startup networking helpers.
|
|
128
129
|
*/
|
|
129
130
|
var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
|
|
130
|
-
const make$
|
|
131
|
+
const make$93 = () => {
|
|
131
132
|
/**
|
|
132
133
|
* Returns true when a TCP server can bind to {host, port}.
|
|
133
134
|
* `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
|
|
@@ -236,10 +237,10 @@ const make$92 = () => {
|
|
|
236
237
|
})
|
|
237
238
|
};
|
|
238
239
|
};
|
|
239
|
-
const layer$82 = Layer.sync(NetService, make$
|
|
240
|
+
const layer$82 = Layer.sync(NetService, make$93);
|
|
240
241
|
//#endregion
|
|
241
242
|
//#region package.json
|
|
242
|
-
var version = "0.4.
|
|
243
|
+
var version = "0.4.9";
|
|
243
244
|
//#endregion
|
|
244
245
|
//#region src/config.ts
|
|
245
246
|
/**
|
|
@@ -260,8 +261,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
|
|
|
260
261
|
/** @deprecated Import and use `layerTest` from this module. */
|
|
261
262
|
static layerTest = (cwd, baseDirOrPrefix) => layerTest$3(cwd, baseDirOrPrefix);
|
|
262
263
|
};
|
|
263
|
-
const make$
|
|
264
|
-
const layer$81 = (config) => Layer.succeed(ServerConfig$1, make$
|
|
264
|
+
const make$92 = (config) => ServerConfig$1.of(config);
|
|
265
|
+
const layer$81 = (config) => Layer.succeed(ServerConfig$1, make$92(config));
|
|
265
266
|
const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
|
|
266
267
|
const { join } = yield* Path.Path;
|
|
267
268
|
const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
|
|
@@ -1321,6 +1322,7 @@ const ServerSelfUpdateCapability = Schema$1.Literals([
|
|
|
1321
1322
|
"desktop-managed"
|
|
1322
1323
|
]);
|
|
1323
1324
|
const ExecutionEnvironmentCapabilities = Schema$1.Struct({
|
|
1325
|
+
threadLifecycleV2: Schema$1.optionalKey(Schema$1.Boolean),
|
|
1324
1326
|
repositoryIdentity: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
|
|
1325
1327
|
connectionProbe: Schema$1.optionalKey(Schema$1.Boolean),
|
|
1326
1328
|
/** Server understands thread.settle / thread.unsettle commands. Absent on
|
|
@@ -2001,7 +2003,31 @@ const ThreadWorkspaceLifecycle = Schema$1.Struct({
|
|
|
2001
2003
|
mergeCommitSha: Schema$1.NullOr(TrimmedNonEmptyString),
|
|
2002
2004
|
updatedAt: IsoDateTime
|
|
2003
2005
|
});
|
|
2006
|
+
const ThreadLifecycle = Schema$1.Literals([
|
|
2007
|
+
"active",
|
|
2008
|
+
"done",
|
|
2009
|
+
"archived"
|
|
2010
|
+
]);
|
|
2011
|
+
const ThreadLifecycleReason = Schema$1.Literals([
|
|
2012
|
+
"created",
|
|
2013
|
+
"manual",
|
|
2014
|
+
"inactivity",
|
|
2015
|
+
"pull-request",
|
|
2016
|
+
"user",
|
|
2017
|
+
"activity",
|
|
2018
|
+
"archive",
|
|
2019
|
+
"restore"
|
|
2020
|
+
]);
|
|
2021
|
+
/** Optional during mixed-version support; v2 servers populate every field. */
|
|
2022
|
+
const ThreadCompletionFields = {
|
|
2023
|
+
lifecycle: Schema$1.optional(ThreadLifecycle),
|
|
2024
|
+
lifecycleChangedAt: Schema$1.optional(IsoDateTime),
|
|
2025
|
+
lifecycleReason: Schema$1.optional(ThreadLifecycleReason),
|
|
2026
|
+
doneAt: Schema$1.optional(Schema$1.NullOr(IsoDateTime)),
|
|
2027
|
+
lastEngagedAt: Schema$1.optional(IsoDateTime)
|
|
2028
|
+
};
|
|
2004
2029
|
const OrchestrationThread = Schema$1.Struct({
|
|
2030
|
+
...ThreadCompletionFields,
|
|
2005
2031
|
id: ThreadId,
|
|
2006
2032
|
projectId: ProjectId,
|
|
2007
2033
|
title: TrimmedNonEmptyString,
|
|
@@ -2105,6 +2131,7 @@ const OrchestrationProjectShell = Schema$1.Struct({
|
|
|
2105
2131
|
updatedAt: IsoDateTime
|
|
2106
2132
|
});
|
|
2107
2133
|
const OrchestrationThreadShell = Schema$1.Struct({
|
|
2134
|
+
...ThreadCompletionFields,
|
|
2108
2135
|
id: ThreadId,
|
|
2109
2136
|
projectId: ProjectId,
|
|
2110
2137
|
title: TrimmedNonEmptyString,
|
|
@@ -2362,6 +2389,25 @@ const ThreadUnsettleCommand = Schema$1.Struct({
|
|
|
2362
2389
|
threadId: ThreadId,
|
|
2363
2390
|
reason: Schema$1.Literal("user")
|
|
2364
2391
|
});
|
|
2392
|
+
const ThreadCompleteCommand = Schema$1.Struct({
|
|
2393
|
+
type: Schema$1.Literal("thread.complete"),
|
|
2394
|
+
commandId: CommandId,
|
|
2395
|
+
threadId: ThreadId
|
|
2396
|
+
});
|
|
2397
|
+
const ThreadReopenCommand = Schema$1.Struct({
|
|
2398
|
+
type: Schema$1.Literal("thread.reopen"),
|
|
2399
|
+
commandId: CommandId,
|
|
2400
|
+
threadId: ThreadId
|
|
2401
|
+
});
|
|
2402
|
+
/** Server effects propose completion against the engagement state they inspected. */
|
|
2403
|
+
const ThreadAutoCompleteCommand = Schema$1.Struct({
|
|
2404
|
+
type: Schema$1.Literal("thread.complete.auto"),
|
|
2405
|
+
commandId: CommandId,
|
|
2406
|
+
threadId: ThreadId,
|
|
2407
|
+
reason: Schema$1.Literals(["inactivity", "pull-request"]),
|
|
2408
|
+
expectedLastEngagedAt: IsoDateTime,
|
|
2409
|
+
eligibleAt: IsoDateTime
|
|
2410
|
+
});
|
|
2365
2411
|
const ThreadSnoozeCommand = Schema$1.Struct({
|
|
2366
2412
|
type: Schema$1.Literal("thread.snooze"),
|
|
2367
2413
|
commandId: CommandId,
|
|
@@ -2590,6 +2636,8 @@ const DispatchableClientOrchestrationCommand = Schema$1.Union([
|
|
|
2590
2636
|
ThreadArchiveCommand,
|
|
2591
2637
|
ThreadUnarchiveCommand,
|
|
2592
2638
|
ThreadSettleCommand,
|
|
2639
|
+
ThreadCompleteCommand,
|
|
2640
|
+
ThreadReopenCommand,
|
|
2593
2641
|
ThreadUnsettleCommand,
|
|
2594
2642
|
ThreadSnoozeCommand,
|
|
2595
2643
|
ThreadUnsnoozeCommand,
|
|
@@ -2624,6 +2672,8 @@ const ClientOrchestrationCommand = Schema$1.Union([
|
|
|
2624
2672
|
ThreadArchiveCommand,
|
|
2625
2673
|
ThreadUnarchiveCommand,
|
|
2626
2674
|
ThreadSettleCommand,
|
|
2675
|
+
ThreadCompleteCommand,
|
|
2676
|
+
ThreadReopenCommand,
|
|
2627
2677
|
ThreadUnsettleCommand,
|
|
2628
2678
|
ThreadSnoozeCommand,
|
|
2629
2679
|
ThreadUnsnoozeCommand,
|
|
@@ -2763,6 +2813,7 @@ const ThreadRevertCompleteCommand = Schema$1.Struct({
|
|
|
2763
2813
|
createdAt: IsoDateTime
|
|
2764
2814
|
});
|
|
2765
2815
|
const InternalOrchestrationCommand = Schema$1.Union([
|
|
2816
|
+
ThreadAutoCompleteCommand,
|
|
2766
2817
|
ThreadSessionSetCommand,
|
|
2767
2818
|
ThreadSessionForceStopConvergeCommand,
|
|
2768
2819
|
ThreadTurnCompleteCommand,
|
|
@@ -2856,6 +2907,7 @@ const ProjectDeletedPayload$1 = Schema$1.Struct({
|
|
|
2856
2907
|
deletedAt: IsoDateTime
|
|
2857
2908
|
});
|
|
2858
2909
|
const ThreadCreatedPayload$1 = Schema$1.Struct({
|
|
2910
|
+
...ThreadCompletionFields,
|
|
2859
2911
|
threadId: ThreadId,
|
|
2860
2912
|
projectId: ProjectId,
|
|
2861
2913
|
title: TrimmedNonEmptyString,
|
|
@@ -2879,20 +2931,24 @@ const ThreadDeletedPayload$1 = Schema$1.Struct({
|
|
|
2879
2931
|
deletedAt: IsoDateTime
|
|
2880
2932
|
});
|
|
2881
2933
|
const ThreadArchivedPayload$1 = Schema$1.Struct({
|
|
2934
|
+
...ThreadCompletionFields,
|
|
2882
2935
|
threadId: ThreadId,
|
|
2883
2936
|
archivedAt: IsoDateTime,
|
|
2884
2937
|
updatedAt: IsoDateTime
|
|
2885
2938
|
});
|
|
2886
2939
|
const ThreadUnarchivedPayload$1 = Schema$1.Struct({
|
|
2940
|
+
...ThreadCompletionFields,
|
|
2887
2941
|
threadId: ThreadId,
|
|
2888
2942
|
updatedAt: IsoDateTime
|
|
2889
2943
|
});
|
|
2890
2944
|
const ThreadSettledPayload$1 = Schema$1.Struct({
|
|
2945
|
+
...ThreadCompletionFields,
|
|
2891
2946
|
threadId: ThreadId,
|
|
2892
2947
|
settledAt: IsoDateTime,
|
|
2893
2948
|
updatedAt: IsoDateTime
|
|
2894
2949
|
});
|
|
2895
2950
|
const ThreadUnsettledPayload$1 = Schema$1.Struct({
|
|
2951
|
+
...ThreadCompletionFields,
|
|
2896
2952
|
threadId: ThreadId,
|
|
2897
2953
|
reason: Schema$1.Literals(["user", "activity"]),
|
|
2898
2954
|
updatedAt: IsoDateTime
|
|
@@ -3696,6 +3752,7 @@ Schema$1.Struct({
|
|
|
3696
3752
|
headRefName: TrimmedNonEmptyString,
|
|
3697
3753
|
state: ChangeRequestState,
|
|
3698
3754
|
updatedAt: Schema$1.Option(Schema$1.DateTimeUtc),
|
|
3755
|
+
terminalAt: Schema$1.optional(Schema$1.NullOr(IsoDateTime)),
|
|
3699
3756
|
isCrossRepository: Schema$1.optional(Schema$1.Boolean),
|
|
3700
3757
|
headRepositoryNameWithOwner: Schema$1.optional(Schema$1.NullOr(TrimmedNonEmptyString)),
|
|
3701
3758
|
headRepositoryOwnerLogin: Schema$1.optional(Schema$1.NullOr(TrimmedNonEmptyString))
|
|
@@ -7637,6 +7694,7 @@ const STATIC_KEYBINDING_COMMANDS = [
|
|
|
7637
7694
|
"preview.zoomOut",
|
|
7638
7695
|
"preview.resetZoom",
|
|
7639
7696
|
"commandPalette.toggle",
|
|
7697
|
+
"workspace.searchContents",
|
|
7640
7698
|
"composer.stash",
|
|
7641
7699
|
"chat.new",
|
|
7642
7700
|
"chat.newLocal",
|
|
@@ -8482,6 +8540,7 @@ const SourceControlWritingStyleSettings = Schema$1.Struct({
|
|
|
8482
8540
|
});
|
|
8483
8541
|
const DEFAULT_AUTOMATIC_GIT_FETCH_INTERVAL = Duration.seconds(30);
|
|
8484
8542
|
const ServerSettings = Schema$1.Struct({
|
|
8543
|
+
threadAutoCompleteAfterDays: Schema$1.NullOr(SidebarAutoSettleAfterDays).pipe(Schema$1.withDecodingDefault(Effect.succeed(3))),
|
|
8485
8544
|
enableAssistantStreaming: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(false))),
|
|
8486
8545
|
enableProviderUpdateChecks: Schema$1.Boolean.pipe(Schema$1.withDecodingDefault(Effect.succeed(true))),
|
|
8487
8546
|
/**
|
|
@@ -8699,6 +8758,7 @@ const OpenCodeSettingsPatch = Schema$1.Struct({
|
|
|
8699
8758
|
customModels: Schema$1.optionalKey(Schema$1.Array(Schema$1.String))
|
|
8700
8759
|
});
|
|
8701
8760
|
const ServerSettingsPatch = Schema$1.Struct({
|
|
8761
|
+
threadAutoCompleteAfterDays: Schema$1.optionalKey(Schema$1.NullOr(SidebarAutoSettleAfterDays)),
|
|
8702
8762
|
enableAssistantStreaming: Schema$1.optionalKey(Schema$1.Boolean),
|
|
8703
8763
|
enableProviderUpdateChecks: Schema$1.optionalKey(Schema$1.Boolean),
|
|
8704
8764
|
enableToolCallNarration: Schema$1.optionalKey(Schema$1.Boolean),
|
|
@@ -9611,6 +9671,23 @@ const ProjectSearchEntriesResult = Schema$1.Struct({
|
|
|
9611
9671
|
entries: Schema$1.Array(ProjectEntry),
|
|
9612
9672
|
truncated: Schema$1.Boolean
|
|
9613
9673
|
});
|
|
9674
|
+
const ProjectSearchContentsInput = Schema$1.Struct({
|
|
9675
|
+
cwd: TrimmedNonEmptyString,
|
|
9676
|
+
query: Schema$1.String.check(Schema$1.isNonEmpty(), Schema$1.isMaxLength(256)),
|
|
9677
|
+
limit: PositiveInt.check(Schema$1.isLessThanOrEqualTo(500))
|
|
9678
|
+
});
|
|
9679
|
+
const ProjectSearchContentsResult = Schema$1.Struct({
|
|
9680
|
+
matches: Schema$1.Array(Schema$1.Struct({
|
|
9681
|
+
path: TrimmedNonEmptyString,
|
|
9682
|
+
lineNumber: PositiveInt,
|
|
9683
|
+
lineContent: Schema$1.String,
|
|
9684
|
+
matchRanges: Schema$1.Array(Schema$1.Struct({
|
|
9685
|
+
start: NonNegativeInt,
|
|
9686
|
+
end: NonNegativeInt
|
|
9687
|
+
}))
|
|
9688
|
+
})),
|
|
9689
|
+
truncated: Schema$1.Boolean
|
|
9690
|
+
});
|
|
9614
9691
|
const ProjectListEntriesInput = Schema$1.Struct({ cwd: TrimmedNonEmptyString });
|
|
9615
9692
|
const ProjectListEntriesResult = Schema$1.Struct({
|
|
9616
9693
|
entries: Schema$1.Array(ProjectEntry),
|
|
@@ -10002,6 +10079,18 @@ const ThreadRenameResult = Schema$1.Struct({
|
|
|
10002
10079
|
threadId: ThreadId,
|
|
10003
10080
|
title: TrimmedNonEmptyString
|
|
10004
10081
|
});
|
|
10082
|
+
const ThreadPlanUpdateInput = Schema$1.Struct({
|
|
10083
|
+
explanation: Schema$1.optional(TrimmedNonEmptyString),
|
|
10084
|
+
plan: Schema$1.Array(Schema$1.Struct({
|
|
10085
|
+
step: TrimmedNonEmptyString,
|
|
10086
|
+
status: Schema$1.Literals([
|
|
10087
|
+
"pending",
|
|
10088
|
+
"in_progress",
|
|
10089
|
+
"completed"
|
|
10090
|
+
])
|
|
10091
|
+
}))
|
|
10092
|
+
});
|
|
10093
|
+
const ThreadPlanUpdateResult = Schema$1.Struct({ threadId: ThreadId });
|
|
10005
10094
|
/**
|
|
10006
10095
|
* Which thread a control tool acts on.
|
|
10007
10096
|
*
|
|
@@ -10040,13 +10129,16 @@ const ThreadSpawnInput = Schema$1.Struct({
|
|
|
10040
10129
|
interactionMode: Schema$1.optional(ProviderInteractionMode),
|
|
10041
10130
|
compressMode: Schema$1.optional(CompressMode),
|
|
10042
10131
|
unpromptedSubagents: Schema$1.optional(Schema$1.Boolean),
|
|
10043
|
-
|
|
10132
|
+
fusion: Schema$1.optional(Schema$1.Boolean.annotate({ description: "Create two new threads as a separate Fusion pair, then start the builder with prompt. Leaves the caller and its existing pair unchanged. Cannot be combined with fusionWatcher." })),
|
|
10133
|
+
fusionWatcher: Schema$1.optional(Schema$1.Boolean.annotate({ description: "Set true only when creating the watcher to pair with the current thread. Defaults to the saved Fusion supervisor model. No special user command syntax is required." }))
|
|
10044
10134
|
});
|
|
10045
10135
|
const ThreadSpawnResult = Schema$1.Struct({
|
|
10046
10136
|
/** Watchable with `thread_watch_events`, and addressable by every tool here. */
|
|
10047
10137
|
threadId: ThreadId,
|
|
10048
10138
|
projectId: ProjectId,
|
|
10049
|
-
title: TrimmedNonEmptyString
|
|
10139
|
+
title: TrimmedNonEmptyString,
|
|
10140
|
+
pairId: Schema$1.optional(ThreadPairId),
|
|
10141
|
+
watcherThreadId: Schema$1.optional(ThreadId)
|
|
10050
10142
|
});
|
|
10051
10143
|
const ThreadPairCreateInput = Schema$1.Struct({
|
|
10052
10144
|
watcherThreadId: ThreadId.annotate({ description: "The supervisor thread to pair with this session's own builder thread. It must have been created by this session through thread_spawn." }),
|
|
@@ -10218,12 +10310,6 @@ var ThreadSpawnNotPermittedError = class extends Schema$1.TaggedErrorClass()("Th
|
|
|
10218
10310
|
return `Thread ${this.threadId} cannot start another thread: ${this.detail}`;
|
|
10219
10311
|
}
|
|
10220
10312
|
};
|
|
10221
|
-
/** Fusion watcher and pair creation require fresh user authorization from this exact thread. */
|
|
10222
|
-
var ThreadPairApprovalRequiredError = class extends Schema$1.TaggedErrorClass()("ThreadPairApprovalRequiredError", { threadId: ThreadId }) {
|
|
10223
|
-
get message() {
|
|
10224
|
-
return `Thread ${this.threadId} cannot create a Fusion watcher or pair without explicit user approval. The latest user message must invoke /fusion or $fusion on its own line, or affirm the immediately preceding assistant proposal that names Fusion and asks for approval.`;
|
|
10225
|
-
}
|
|
10226
|
-
};
|
|
10227
10313
|
/** The orchestration engine declined or failed a thread control command. */
|
|
10228
10314
|
var ThreadControlRejectedError = class extends Schema$1.TaggedErrorClass()("ThreadControlRejectedError", {
|
|
10229
10315
|
threadId: ThreadId,
|
|
@@ -10238,7 +10324,6 @@ const ThreadControlToolError = Schema$1.Union([
|
|
|
10238
10324
|
ThreadToolUnavailableError,
|
|
10239
10325
|
ThreadControlNotPermittedError,
|
|
10240
10326
|
ThreadSpawnNotPermittedError,
|
|
10241
|
-
ThreadPairApprovalRequiredError,
|
|
10242
10327
|
ThreadControlRejectedError,
|
|
10243
10328
|
ThreadRenameRejectedError,
|
|
10244
10329
|
MemoryAppendFailedError,
|
|
@@ -10262,6 +10347,45 @@ const ThreadWatchEventsResult = Schema$1.Struct({
|
|
|
10262
10347
|
/** True when more events for this thread exist past the returned page. */
|
|
10263
10348
|
hasMore: Schema$1.Boolean
|
|
10264
10349
|
});
|
|
10350
|
+
/** Compact review limits are server-owned, independent of raw event paging. */
|
|
10351
|
+
const THREAD_REVIEW_SCAN_LIMIT = 2e3;
|
|
10352
|
+
const THREAD_REVIEW_ITEM_MAX_BYTES = 8e3;
|
|
10353
|
+
const ThreadWatchReviewInput = Schema$1.Struct({
|
|
10354
|
+
threadId: ThreadId,
|
|
10355
|
+
afterSequence: Schema$1.optional(NonNegativeInt),
|
|
10356
|
+
throughSequence: Schema$1.optional(NonNegativeInt.annotate({ description: "Inclusive fixed review boundary. Omit on the first page to capture the head; reuse the returned boundary on every subsequent page." }))
|
|
10357
|
+
});
|
|
10358
|
+
const ReviewSourceFields = {
|
|
10359
|
+
firstSequence: NonNegativeInt,
|
|
10360
|
+
lastSequence: NonNegativeInt,
|
|
10361
|
+
truncated: Schema$1.Boolean
|
|
10362
|
+
};
|
|
10363
|
+
const ThreadReviewItem = Schema$1.Union([Schema$1.Struct({
|
|
10364
|
+
...ReviewSourceFields,
|
|
10365
|
+
kind: Schema$1.Literal("message"),
|
|
10366
|
+
messageId: Schema$1.String,
|
|
10367
|
+
turnId: Schema$1.NullOr(Schema$1.String),
|
|
10368
|
+
role: Schema$1.String,
|
|
10369
|
+
/** Apply append/replace by message identity across page boundaries. */
|
|
10370
|
+
operation: Schema$1.Literals(["append", "replace"]),
|
|
10371
|
+
complete: Schema$1.Boolean,
|
|
10372
|
+
text: Schema$1.String
|
|
10373
|
+
}), Schema$1.Struct({
|
|
10374
|
+
...ReviewSourceFields,
|
|
10375
|
+
kind: Schema$1.Literal("event"),
|
|
10376
|
+
type: Schema$1.String,
|
|
10377
|
+
/** JSON evidence excerpt. Truncated excerpts require targeted raw recovery. */
|
|
10378
|
+
payload: Schema$1.String
|
|
10379
|
+
})]);
|
|
10380
|
+
const ThreadWatchReviewResult = Schema$1.Struct({
|
|
10381
|
+
threadId: ThreadId,
|
|
10382
|
+
items: Schema$1.Array(ThreadReviewItem),
|
|
10383
|
+
throughSequence: NonNegativeInt,
|
|
10384
|
+
/** Resume from the source scan cursor, even when items is empty. */
|
|
10385
|
+
nextAfterSequence: NonNegativeInt,
|
|
10386
|
+
hasMore: Schema$1.Boolean,
|
|
10387
|
+
scannedEvents: NonNegativeInt
|
|
10388
|
+
});
|
|
10265
10389
|
var WatchToolUnavailableError = class extends Schema$1.TaggedErrorClass()("WatchToolUnavailableError", {
|
|
10266
10390
|
capability: Schema$1.Literal("watch"),
|
|
10267
10391
|
environmentId: EnvironmentId,
|
|
@@ -11527,6 +11651,7 @@ const WS_METHODS = {
|
|
|
11527
11651
|
projectsRemove: "projects.remove",
|
|
11528
11652
|
projectsListEntries: "projects.listEntries",
|
|
11529
11653
|
projectsReadFile: "projects.readFile",
|
|
11654
|
+
projectsSearchContents: "projects.searchContents",
|
|
11530
11655
|
projectsSearchEntries: "projects.searchEntries",
|
|
11531
11656
|
projectsWriteFile: "projects.writeFile",
|
|
11532
11657
|
shellOpenInEditor: "shell.openInEditor",
|
|
@@ -12237,6 +12362,11 @@ const WsSourceControlPublishRepositoryRpc = Rpc.make(WS_METHODS.sourceControlPub
|
|
|
12237
12362
|
success: SourceControlPublishRepositoryResult,
|
|
12238
12363
|
error: Schema$1.Union([SourceControlRepositoryError, EnvironmentAuthorizationError])
|
|
12239
12364
|
});
|
|
12365
|
+
const WsProjectsSearchContentsRpc = Rpc.make(WS_METHODS.projectsSearchContents, {
|
|
12366
|
+
payload: ProjectSearchContentsInput,
|
|
12367
|
+
success: ProjectSearchContentsResult,
|
|
12368
|
+
error: Schema$1.Union([ProjectSearchEntriesError, EnvironmentAuthorizationError])
|
|
12369
|
+
});
|
|
12240
12370
|
const WsProjectsSearchEntriesRpc = Rpc.make(WS_METHODS.projectsSearchEntries, {
|
|
12241
12371
|
payload: ProjectSearchEntriesInput,
|
|
12242
12372
|
success: ProjectSearchEntriesResult,
|
|
@@ -12502,7 +12632,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
|
|
|
12502
12632
|
error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
|
|
12503
12633
|
stream: true
|
|
12504
12634
|
});
|
|
12505
|
-
const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsBtwAskRpc, WsBtwCancelRpc, WsServerGetUsageSummaryRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, WsPullRequestsActivityRpc, WsPullRequestsDiffFileContentsRpc, WsPullRequestsRunActionRpc, WsPullRequestsUpdateRpc, WsPullRequestsCommentRpc, WsPullRequestsUpdateCommentRpc, WsPullRequestsSubmitReviewRpc, WsPullRequestsReplyToThreadRpc, WsPullRequestsSetThreadResolutionRpc, WsPullRequestsSetReactionRpc, WsPullRequestsInvalidateRpc, WsPullRequestsReviewerCandidatesRpc, WsPullRequestsRequestReviewersRpc, WsSourceControlLookupRepositoryRpc, WsSourceControlCloneRepositoryRpc, WsSourceControlPublishRepositoryRpc, WsProjectsListEntriesRpc, WsProjectsReadFileRpc, 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, 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, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationSearchThreadsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
12635
|
+
const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, WsBtwAskRpc, WsBtwCancelRpc, WsServerGetUsageSummaryRpc, WsServerGetTraceDiagnosticsRpc, WsServerGetProcessDiagnosticsRpc, WsServerGetProcessResourceHistoryRpc, WsServerSignalProcessRpc, WsPullRequestsListRpc, WsPullRequestsListStatsRpc, WsPullRequestsDetailRpc, 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, 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, WsOrchestrationGetFullThreadDiffRpc, WsOrchestrationSearchThreadsRpc, WsOrchestrationGetArchivedShellSnapshotRpc, WsOrchestrationSubscribeShellRpc, WsOrchestrationSubscribeThreadRpc);
|
|
12506
12636
|
//#endregion
|
|
12507
12637
|
//#region ../../packages/shared/src/oauthScope.ts
|
|
12508
12638
|
const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
|
|
@@ -12648,7 +12778,7 @@ function deriveAuthClientMetadata(input) {
|
|
|
12648
12778
|
//#endregion
|
|
12649
12779
|
//#region src/auth/EnvironmentAuthPolicy.ts
|
|
12650
12780
|
var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
|
|
12651
|
-
const make$
|
|
12781
|
+
const make$91 = Effect.gen(function* () {
|
|
12652
12782
|
const config = yield* ServerConfig$1;
|
|
12653
12783
|
const isRemoteReachable = isRemoteReachableHost(config.host);
|
|
12654
12784
|
const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
|
|
@@ -12666,7 +12796,7 @@ const make$90 = Effect.gen(function* () {
|
|
|
12666
12796
|
};
|
|
12667
12797
|
return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
|
|
12668
12798
|
});
|
|
12669
|
-
const layer$80 = Layer.effect(EnvironmentAuthPolicy, make$
|
|
12799
|
+
const layer$80 = Layer.effect(EnvironmentAuthPolicy, make$91);
|
|
12670
12800
|
//#endregion
|
|
12671
12801
|
//#region src/persistence/Errors.ts
|
|
12672
12802
|
function summarizeSchemaIssue(issue) {
|
|
@@ -12847,7 +12977,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
|
|
|
12847
12977
|
cause
|
|
12848
12978
|
});
|
|
12849
12979
|
}
|
|
12850
|
-
const make$
|
|
12980
|
+
const make$90 = Effect.gen(function* () {
|
|
12851
12981
|
const sql = yield* SqlClient.SqlClient;
|
|
12852
12982
|
const createSessionRow = SqlSchema.void({
|
|
12853
12983
|
Request: CreateAuthSessionInput,
|
|
@@ -12981,7 +13111,7 @@ const make$89 = Effect.gen(function* () {
|
|
|
12981
13111
|
setLastConnectedAt
|
|
12982
13112
|
};
|
|
12983
13113
|
});
|
|
12984
|
-
const layer$79 = Layer.effect(AuthSessionRepository, make$
|
|
13114
|
+
const layer$79 = Layer.effect(AuthSessionRepository, make$90);
|
|
12985
13115
|
//#endregion
|
|
12986
13116
|
//#region src/auth/ServerSecretStore.ts
|
|
12987
13117
|
const secretStoreErrorContext = {
|
|
@@ -13048,7 +13178,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
|
|
|
13048
13178
|
const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
|
|
13049
13179
|
const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
|
|
13050
13180
|
var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
|
|
13051
|
-
const make$
|
|
13181
|
+
const make$89 = Effect.gen(function* () {
|
|
13052
13182
|
const crypto = yield* Crypto.Crypto;
|
|
13053
13183
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
13054
13184
|
const path = yield* Path.Path;
|
|
@@ -13124,7 +13254,7 @@ const make$88 = Effect.gen(function* () {
|
|
|
13124
13254
|
remove
|
|
13125
13255
|
});
|
|
13126
13256
|
});
|
|
13127
|
-
const layer$78 = Layer.effect(ServerSecretStore, make$
|
|
13257
|
+
const layer$78 = Layer.effect(ServerSecretStore, make$89);
|
|
13128
13258
|
//#endregion
|
|
13129
13259
|
//#region src/auth/SessionStore.ts
|
|
13130
13260
|
var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
|
|
@@ -13362,7 +13492,7 @@ function toAuthClientSession(input) {
|
|
|
13362
13492
|
current: false
|
|
13363
13493
|
};
|
|
13364
13494
|
}
|
|
13365
|
-
const make$
|
|
13495
|
+
const make$88 = Effect.gen(function* () {
|
|
13366
13496
|
const crypto = yield* Crypto.Crypto;
|
|
13367
13497
|
const serverConfig = yield* ServerConfig$1;
|
|
13368
13498
|
const secretStore = yield* ServerSecretStore;
|
|
@@ -13676,7 +13806,7 @@ const make$87 = Effect.gen(function* () {
|
|
|
13676
13806
|
markDisconnected
|
|
13677
13807
|
});
|
|
13678
13808
|
});
|
|
13679
|
-
const layer$77 = Layer.effect(SessionStore, make$
|
|
13809
|
+
const layer$77 = Layer.effect(SessionStore, make$88).pipe(Layer.provideMerge(layer$79));
|
|
13680
13810
|
//#endregion
|
|
13681
13811
|
//#region src/persistence/AuthPairingLinks.ts
|
|
13682
13812
|
const AuthPairingLinkRecord = Schema$1.Struct({
|
|
@@ -13737,7 +13867,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
|
|
|
13737
13867
|
cause
|
|
13738
13868
|
});
|
|
13739
13869
|
}
|
|
13740
|
-
const make$
|
|
13870
|
+
const make$87 = Effect.gen(function* () {
|
|
13741
13871
|
const sql = yield* SqlClient.SqlClient;
|
|
13742
13872
|
const createPairingLinkRow = SqlSchema.void({
|
|
13743
13873
|
Request: CreateAuthPairingLinkInput,
|
|
@@ -13872,7 +14002,7 @@ const make$86 = Effect.gen(function* () {
|
|
|
13872
14002
|
getByCredential
|
|
13873
14003
|
};
|
|
13874
14004
|
});
|
|
13875
|
-
const layer$76 = Layer.effect(AuthPairingLinkRepository, make$
|
|
14005
|
+
const layer$76 = Layer.effect(AuthPairingLinkRepository, make$87);
|
|
13876
14006
|
//#endregion
|
|
13877
14007
|
//#region src/auth/PairingGrantStore.ts
|
|
13878
14008
|
var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
|
|
@@ -13967,7 +14097,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
|
|
|
13967
14097
|
const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
|
|
13968
14098
|
const PAIRING_TOKEN_LENGTH = 12;
|
|
13969
14099
|
const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
|
|
13970
|
-
const make$
|
|
14100
|
+
const make$86 = Effect.gen(function* () {
|
|
13971
14101
|
const crypto = yield* Crypto.Crypto;
|
|
13972
14102
|
const config = yield* ServerConfig$1;
|
|
13973
14103
|
const pairingLinks = yield* AuthPairingLinkRepository;
|
|
@@ -14165,7 +14295,7 @@ const make$85 = Effect.gen(function* () {
|
|
|
14165
14295
|
consume
|
|
14166
14296
|
});
|
|
14167
14297
|
});
|
|
14168
|
-
const layer$75 = Layer.effect(PairingGrantStore, make$
|
|
14298
|
+
const layer$75 = Layer.effect(PairingGrantStore, make$86).pipe(Layer.provideMerge(layer$76));
|
|
14169
14299
|
//#endregion
|
|
14170
14300
|
//#region src/persistence/DatabaseSnapshot.ts
|
|
14171
14301
|
/**
|
|
@@ -16111,6 +16241,31 @@ var _054_ProjectionThreadScheduledTasks_default = Effect.gen(function* () {
|
|
|
16111
16241
|
`;
|
|
16112
16242
|
});
|
|
16113
16243
|
//#endregion
|
|
16244
|
+
//#region src/persistence/Migrations/055_ThreadCompletionLifecycle.ts
|
|
16245
|
+
var _055_ThreadCompletionLifecycle_default = Effect.gen(function* () {
|
|
16246
|
+
const sql = yield* SqlClient.SqlClient;
|
|
16247
|
+
yield* sql`ALTER TABLE projection_threads ADD COLUMN lifecycle TEXT NOT NULL DEFAULT 'active'`;
|
|
16248
|
+
yield* sql`ALTER TABLE projection_threads ADD COLUMN lifecycle_reason TEXT NOT NULL DEFAULT 'created'`;
|
|
16249
|
+
yield* sql`ALTER TABLE projection_threads ADD COLUMN lifecycle_changed_at TEXT`;
|
|
16250
|
+
yield* sql`ALTER TABLE projection_threads ADD COLUMN last_engaged_at TEXT`;
|
|
16251
|
+
yield* sql`
|
|
16252
|
+
UPDATE projection_threads SET
|
|
16253
|
+
lifecycle = CASE WHEN archived_at IS NOT NULL THEN 'archived'
|
|
16254
|
+
WHEN settled_override = 'settled' THEN 'done' ELSE 'active' END,
|
|
16255
|
+
lifecycle_reason = CASE WHEN archived_at IS NOT NULL THEN 'archive'
|
|
16256
|
+
WHEN settled_override = 'settled' THEN 'manual' ELSE 'created' END,
|
|
16257
|
+
lifecycle_changed_at = COALESCE(archived_at, settled_at, created_at),
|
|
16258
|
+
last_engaged_at = MAX(created_at, COALESCE(latest_user_message_at, created_at),
|
|
16259
|
+
COALESCE((SELECT MAX(message.updated_at) FROM projection_thread_messages message
|
|
16260
|
+
WHERE message.thread_id = projection_threads.thread_id AND message.role IN ('user', 'assistant')), created_at)),
|
|
16261
|
+
settled_override = CASE WHEN settled_override = 'settled' THEN 'settled' ELSE 'active' END
|
|
16262
|
+
`;
|
|
16263
|
+
yield* sql`CREATE INDEX idx_projection_threads_lifecycle_sweep
|
|
16264
|
+
ON projection_threads(lifecycle, deleted_at, thread_id)`;
|
|
16265
|
+
yield* sql`CREATE INDEX idx_projection_threads_lifecycle_inactivity
|
|
16266
|
+
ON projection_threads(lifecycle, deleted_at, last_engaged_at, thread_id)`;
|
|
16267
|
+
});
|
|
16268
|
+
//#endregion
|
|
16114
16269
|
//#region src/persistence/Migrations.ts
|
|
16115
16270
|
/**
|
|
16116
16271
|
* MigrationsLive - Migration runner with inline loader
|
|
@@ -16401,6 +16556,11 @@ const migrationEntries = [
|
|
|
16401
16556
|
54,
|
|
16402
16557
|
"ProjectionThreadScheduledTasks",
|
|
16403
16558
|
_054_ProjectionThreadScheduledTasks_default
|
|
16559
|
+
],
|
|
16560
|
+
[
|
|
16561
|
+
55,
|
|
16562
|
+
"ThreadCompletionLifecycle",
|
|
16563
|
+
_055_ThreadCompletionLifecycle_default
|
|
16404
16564
|
]
|
|
16405
16565
|
];
|
|
16406
16566
|
const makeMigrationLoader = (throughId) => Migrator.fromRecord(Object.fromEntries(migrationEntries.filter(([id]) => throughId === void 0 || id <= throughId).map(([id, name, migration]) => [`${id}_${name}`, migration])));
|
|
@@ -16996,12 +17156,42 @@ function dropStaleContextWindowActivities(activities) {
|
|
|
16996
17156
|
return [index === breakdownIndex ? activity : withoutContextWindowBreakdown$1(activity)];
|
|
16997
17157
|
});
|
|
16998
17158
|
}
|
|
17159
|
+
function toolLifecycleIdentity(activity) {
|
|
17160
|
+
return asTrimmedString$2(asRecord$6(asRecord$6(activity.payload)?.data)?.toolCallId);
|
|
17161
|
+
}
|
|
17162
|
+
/** Clients retain fields missing from a completion when folding an update. */
|
|
17163
|
+
function completionPreservesUpdate(update, completion) {
|
|
17164
|
+
const updatePayload = asRecord$6(update.payload);
|
|
17165
|
+
const completionPayload = asRecord$6(completion.payload);
|
|
17166
|
+
if (!updatePayload || !completionPayload) return false;
|
|
17167
|
+
return Object.entries(updatePayload).every(([key, value]) => key === "status" || NodeUtil.isDeepStrictEqual(value, completionPayload[key]));
|
|
17168
|
+
}
|
|
17169
|
+
/** Remove only updates superseded by a later completion in the same turn. */
|
|
17170
|
+
function dropSupersededToolUpdatedActivities(activities) {
|
|
17171
|
+
const lastCompletionIndexByKey = /* @__PURE__ */ new Map();
|
|
17172
|
+
for (let index = 0; index < activities.length; index += 1) {
|
|
17173
|
+
const activity = activities[index];
|
|
17174
|
+
if (activity.kind !== "tool.completed") continue;
|
|
17175
|
+
const identity = toolLifecycleIdentity(activity);
|
|
17176
|
+
if (!identity) continue;
|
|
17177
|
+
const key = `${activity.turnId ?? ""}\u0000${identity}`;
|
|
17178
|
+
lastCompletionIndexByKey.set(key, index);
|
|
17179
|
+
}
|
|
17180
|
+
if (lastCompletionIndexByKey.size === 0) return activities;
|
|
17181
|
+
return activities.filter((activity, index) => {
|
|
17182
|
+
if (activity.kind !== "tool.updated") return true;
|
|
17183
|
+
const identity = toolLifecycleIdentity(activity);
|
|
17184
|
+
if (!identity) return true;
|
|
17185
|
+
const completionIndex = lastCompletionIndexByKey.get(`${activity.turnId ?? ""}\u0000${identity}`);
|
|
17186
|
+
return completionIndex === void 0 || completionIndex <= index || !completionPreservesUpdate(activity, activities[completionIndex]);
|
|
17187
|
+
});
|
|
17188
|
+
}
|
|
16999
17189
|
function projectThreadDetailSnapshot(snapshot) {
|
|
17000
17190
|
return {
|
|
17001
17191
|
...snapshot,
|
|
17002
17192
|
thread: {
|
|
17003
17193
|
...snapshot.thread,
|
|
17004
|
-
activities: dropStaleContextWindowActivities(snapshot.thread.activities).map(projectActivityPayload)
|
|
17194
|
+
activities: dropSupersededToolUpdatedActivities(dropStaleContextWindowActivities(snapshot.thread.activities).map(projectActivityPayload))
|
|
17005
17195
|
}
|
|
17006
17196
|
};
|
|
17007
17197
|
}
|
|
@@ -17399,7 +17589,7 @@ function parseBearerToken(request) {
|
|
|
17399
17589
|
const token = header.slice(7).trim();
|
|
17400
17590
|
return token.length > 0 ? token : null;
|
|
17401
17591
|
}
|
|
17402
|
-
const make$
|
|
17592
|
+
const make$85 = Effect.gen(function* () {
|
|
17403
17593
|
const policy = yield* EnvironmentAuthPolicy;
|
|
17404
17594
|
const bootstrapCredentials = yield* PairingGrantStore;
|
|
17405
17595
|
const sessions = yield* SessionStore;
|
|
@@ -17594,7 +17784,7 @@ const make$84 = Effect.gen(function* () {
|
|
|
17594
17784
|
issueStartupPairingUrl
|
|
17595
17785
|
});
|
|
17596
17786
|
});
|
|
17597
|
-
const layer$74 = Layer.effect(EnvironmentAuth, make$
|
|
17787
|
+
const layer$74 = Layer.effect(EnvironmentAuth, make$85).pipe(Layer.provideMerge(layer$75), Layer.provideMerge(layer$77), Layer.provideMerge(layer$80));
|
|
17598
17788
|
const storageLayer = Layer.mergeAll(layer$78, layerConfig);
|
|
17599
17789
|
const runtimeLayer = layer$74.pipe(Layer.provideMerge(storageLayer));
|
|
17600
17790
|
//#endregion
|
|
@@ -19432,7 +19622,7 @@ const DEFAULT_LIMITS = {
|
|
|
19432
19622
|
windowMillis: FAILURE_WINDOW_MS,
|
|
19433
19623
|
blockMillis: BLOCK_DURATION_MS
|
|
19434
19624
|
};
|
|
19435
|
-
const make$
|
|
19625
|
+
const make$84 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
|
|
19436
19626
|
const state = yield* Ref.make(initialThrottleState);
|
|
19437
19627
|
return HubAuthThrottle.of({
|
|
19438
19628
|
shouldRefuse: Effect.gen(function* () {
|
|
@@ -19446,7 +19636,7 @@ const make$83 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
|
|
|
19446
19636
|
})
|
|
19447
19637
|
});
|
|
19448
19638
|
});
|
|
19449
|
-
const layer$73 = Layer.effect(HubAuthThrottle, make$
|
|
19639
|
+
const layer$73 = Layer.effect(HubAuthThrottle, make$84());
|
|
19450
19640
|
//#endregion
|
|
19451
19641
|
//#region src/hub/HubAuth.ts
|
|
19452
19642
|
/**
|
|
@@ -21166,7 +21356,7 @@ function stripDefaultServerSettings(current, defaults) {
|
|
|
21166
21356
|
}
|
|
21167
21357
|
return Object.is(current, defaults) ? void 0 : current;
|
|
21168
21358
|
}
|
|
21169
|
-
const make$
|
|
21359
|
+
const make$83 = Effect.gen(function* () {
|
|
21170
21360
|
const { settingsPath } = yield* ServerConfig$1;
|
|
21171
21361
|
const fs = yield* FileSystem.FileSystem;
|
|
21172
21362
|
const pathService = yield* Path.Path;
|
|
@@ -21387,7 +21577,7 @@ const make$82 = Effect.gen(function* () {
|
|
|
21387
21577
|
}
|
|
21388
21578
|
};
|
|
21389
21579
|
});
|
|
21390
|
-
const layer$71 = Layer.effect(ServerSettingsService, make$
|
|
21580
|
+
const layer$71 = Layer.effect(ServerSettingsService, make$83);
|
|
21391
21581
|
//#endregion
|
|
21392
21582
|
//#region src/pathExpansion.ts
|
|
21393
21583
|
/**
|
|
@@ -21764,7 +21954,7 @@ function claudeEntryFromRegistration(registration) {
|
|
|
21764
21954
|
};
|
|
21765
21955
|
}
|
|
21766
21956
|
var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
|
|
21767
|
-
const make$
|
|
21957
|
+
const make$82 = Effect.gen(function* () {
|
|
21768
21958
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
21769
21959
|
const path = yield* Path.Path;
|
|
21770
21960
|
const services = yield* Effect.context();
|
|
@@ -21831,7 +22021,7 @@ const make$81 = Effect.gen(function* () {
|
|
|
21831
22021
|
removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
|
|
21832
22022
|
};
|
|
21833
22023
|
});
|
|
21834
|
-
const layer$70 = Layer.effect(ClaudeMcpFiles, make$
|
|
22024
|
+
const layer$70 = Layer.effect(ClaudeMcpFiles, make$82);
|
|
21835
22025
|
Layer.succeed(ClaudeMcpFiles, {
|
|
21836
22026
|
readUser: Effect.succeed([]),
|
|
21837
22027
|
readUserAt: () => Effect.succeed([]),
|
|
@@ -21969,7 +22159,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
|
|
|
21969
22159
|
const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
|
|
21970
22160
|
var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
|
|
21971
22161
|
const registryError = (detail) => new McpRegistryError({ detail });
|
|
21972
|
-
const make$
|
|
22162
|
+
const make$81 = Effect.gen(function* () {
|
|
21973
22163
|
const config = yield* ServerConfig$1;
|
|
21974
22164
|
const secrets = yield* ServerSecretStore;
|
|
21975
22165
|
const http = yield* HttpClient.HttpClient;
|
|
@@ -22289,7 +22479,7 @@ const make$80 = Effect.gen(function* () {
|
|
|
22289
22479
|
accessTokenFor
|
|
22290
22480
|
};
|
|
22291
22481
|
});
|
|
22292
|
-
const layer$69 = Layer.effect(McpOAuth, make$
|
|
22482
|
+
const layer$69 = Layer.effect(McpOAuth, make$81);
|
|
22293
22483
|
Layer.succeed(McpOAuth, {
|
|
22294
22484
|
statusFor: () => Effect.succeed(Option.none()),
|
|
22295
22485
|
begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
|
|
@@ -22307,7 +22497,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
|
|
|
22307
22497
|
const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
|
|
22308
22498
|
var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
|
|
22309
22499
|
const slotsOf = (registration) => registration.secrets ?? [];
|
|
22310
|
-
const make$
|
|
22500
|
+
const make$80 = Effect.gen(function* () {
|
|
22311
22501
|
const config = yield* ServerConfig$1;
|
|
22312
22502
|
const secrets = yield* ServerSecretStore;
|
|
22313
22503
|
const oauth = yield* McpOAuth;
|
|
@@ -22481,7 +22671,7 @@ const make$79 = Effect.gen(function* () {
|
|
|
22481
22671
|
resolveForSessionAtClaudeUserConfigPath
|
|
22482
22672
|
};
|
|
22483
22673
|
});
|
|
22484
|
-
const layer$68 = Layer.effect(McpRegistry, make$
|
|
22674
|
+
const layer$68 = Layer.effect(McpRegistry, make$80);
|
|
22485
22675
|
//#endregion
|
|
22486
22676
|
//#region src/sync/skillDirectory.ts
|
|
22487
22677
|
/**
|
|
@@ -22860,7 +23050,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
|
|
|
22860
23050
|
shareMode: input.shareMode
|
|
22861
23051
|
});
|
|
22862
23052
|
const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
|
|
22863
|
-
const make$
|
|
23053
|
+
const make$79 = Effect.fn("HubLink.make")(function* (environment) {
|
|
22864
23054
|
const secrets = yield* ServerSecretStore;
|
|
22865
23055
|
const env = environment ?? process.env;
|
|
22866
23056
|
const fromEnv = fromEnvironment(env);
|
|
@@ -22926,7 +23116,7 @@ const make$78 = Effect.fn("HubLink.make")(function* (environment) {
|
|
|
22926
23116
|
})
|
|
22927
23117
|
};
|
|
22928
23118
|
});
|
|
22929
|
-
const layer$67 = Layer.effect(HubLink, make$
|
|
23119
|
+
const layer$67 = Layer.effect(HubLink, make$79());
|
|
22930
23120
|
//#endregion
|
|
22931
23121
|
//#region src/sync/HubAssetClient.ts
|
|
22932
23122
|
/**
|
|
@@ -22959,7 +23149,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
|
|
|
22959
23149
|
const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
|
|
22960
23150
|
const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
|
|
22961
23151
|
var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
|
|
22962
|
-
const make$
|
|
23152
|
+
const make$78 = Effect.gen(function* () {
|
|
22963
23153
|
const http = yield* HttpClient.HttpClient;
|
|
22964
23154
|
const link = yield* HubLink;
|
|
22965
23155
|
const requireSettings = Effect.gen(function* () {
|
|
@@ -23041,7 +23231,7 @@ const make$77 = Effect.gen(function* () {
|
|
|
23041
23231
|
remove
|
|
23042
23232
|
};
|
|
23043
23233
|
});
|
|
23044
|
-
const layer$66 = Layer.effect(HubAssetClient, make$
|
|
23234
|
+
const layer$66 = Layer.effect(HubAssetClient, make$78);
|
|
23045
23235
|
//#endregion
|
|
23046
23236
|
//#region src/sync/mcpRegistrationFiles.ts
|
|
23047
23237
|
/**
|
|
@@ -23647,7 +23837,7 @@ const EMPTY_REPORT = {
|
|
|
23647
23837
|
unavailable: null
|
|
23648
23838
|
};
|
|
23649
23839
|
var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
|
|
23650
|
-
const make$
|
|
23840
|
+
const make$77 = Effect.gen(function* () {
|
|
23651
23841
|
const client = yield* HubAssetClient;
|
|
23652
23842
|
const link = yield* HubLink;
|
|
23653
23843
|
const settingsStore = yield* ServerSettingsService;
|
|
@@ -24357,7 +24547,7 @@ const make$76 = Effect.gen(function* () {
|
|
|
24357
24547
|
removeLocal
|
|
24358
24548
|
};
|
|
24359
24549
|
});
|
|
24360
|
-
const layer$65 = Layer.effect(AssetSync, make$
|
|
24550
|
+
const layer$65 = Layer.effect(AssetSync, make$77);
|
|
24361
24551
|
//#endregion
|
|
24362
24552
|
//#region src/provider/CompressPrompts.ts
|
|
24363
24553
|
/**
|
|
@@ -25434,6 +25624,30 @@ function toPersistenceSqlOrDecodeError$4(sqlOperation, decodeOperation) {
|
|
|
25434
25624
|
}
|
|
25435
25625
|
const makeEventStore = Effect.gen(function* () {
|
|
25436
25626
|
const sql = yield* SqlClient.SqlClient;
|
|
25627
|
+
const readReviewRows = SqlSchema.findAll({
|
|
25628
|
+
Request: Schema$1.Struct({
|
|
25629
|
+
afterSequence: NonNegativeInt,
|
|
25630
|
+
throughSequence: NonNegativeInt,
|
|
25631
|
+
limit: NonNegativeInt
|
|
25632
|
+
}),
|
|
25633
|
+
Result: Schema$1.Struct({
|
|
25634
|
+
sequence: NonNegativeInt,
|
|
25635
|
+
type: Schema$1.String,
|
|
25636
|
+
aggregateKind: Schema$1.String,
|
|
25637
|
+
aggregateId: Schema$1.String,
|
|
25638
|
+
payloadJson: Schema$1.String
|
|
25639
|
+
}),
|
|
25640
|
+
execute: (request) => sql`
|
|
25641
|
+
SELECT sequence, event_type AS "type", aggregate_kind AS "aggregateKind",
|
|
25642
|
+
stream_id AS "aggregateId",
|
|
25643
|
+
substr(payload_json, 1, ${8001}) AS "payloadJson"
|
|
25644
|
+
FROM orchestration_events
|
|
25645
|
+
WHERE sequence > ${request.afterSequence} AND sequence <= ${request.throughSequence}
|
|
25646
|
+
ORDER BY sequence ASC
|
|
25647
|
+
LIMIT ${Math.min(request.limit, THREAD_REVIEW_SCAN_LIMIT)}
|
|
25648
|
+
`
|
|
25649
|
+
});
|
|
25650
|
+
const readReviewPage = (input) => readReviewRows(input).pipe(Effect.mapError(toPersistenceSqlOrDecodeError$4("OrchestrationEventStore.readReviewPage:query", "OrchestrationEventStore.readReviewPage:decode")));
|
|
25437
25651
|
const appendEventRow = SqlSchema.findOne({
|
|
25438
25652
|
Request: AppendEventRequestSchema,
|
|
25439
25653
|
Result: OrchestrationEventPersistedRowSchema,
|
|
@@ -25603,6 +25817,7 @@ const makeEventStore = Effect.gen(function* () {
|
|
|
25603
25817
|
append,
|
|
25604
25818
|
readByCommandId,
|
|
25605
25819
|
readFromSequence,
|
|
25820
|
+
readReviewPage,
|
|
25606
25821
|
readAll: () => readFromSequence(0, Number.MAX_SAFE_INTEGER)
|
|
25607
25822
|
};
|
|
25608
25823
|
});
|
|
@@ -25727,6 +25942,99 @@ function toProjectorDecodeError(eventType) {
|
|
|
25727
25942
|
});
|
|
25728
25943
|
}
|
|
25729
25944
|
//#endregion
|
|
25945
|
+
//#region ../../packages/shared/src/taskAgentKind.ts
|
|
25946
|
+
/** Unknown task types remain agents; only known background types are excluded. */
|
|
25947
|
+
function classifyTaskAgentKind(input) {
|
|
25948
|
+
const taskType = input.taskType ?? input.subagentType;
|
|
25949
|
+
const nonAgent = taskType != null && (INERT_TASK_TYPES.has(taskType) || MONITOR_TASK_TYPES.has(taskType));
|
|
25950
|
+
if (input.agentId?.trim()) return taskType == null || nonAgent ? "background" : "agent";
|
|
25951
|
+
return nonAgent ? "background" : "agent";
|
|
25952
|
+
}
|
|
25953
|
+
//#endregion
|
|
25954
|
+
//#region src/orchestration/ThreadBackgroundLiveness.ts
|
|
25955
|
+
/**
|
|
25956
|
+
* ThreadBackgroundLivenessService - in-memory per-thread background liveness
|
|
25957
|
+
* for the sidebar status pill.
|
|
25958
|
+
*
|
|
25959
|
+
* The turn can settle while native background work runs on (subagent fleets,
|
|
25960
|
+
* workflow runs, Monitor watch loops); the shell previously showed nothing.
|
|
25961
|
+
* Ingestion records task lifecycle transitions and the shell query reads the
|
|
25962
|
+
* derived state at mapping time — no persistence, no migration. After a
|
|
25963
|
+
* server restart the registry is empty until new task events arrive, which
|
|
25964
|
+
* matches reality: orphaned background work is not live.
|
|
25965
|
+
*
|
|
25966
|
+
* "monitoring" is reserved for watch loops (monitor tasks and background
|
|
25967
|
+
* shells) when they are the ONLY live work; any agent work presents as
|
|
25968
|
+
* "working".
|
|
25969
|
+
*
|
|
25970
|
+
* @module ThreadBackgroundLivenessService
|
|
25971
|
+
*/
|
|
25972
|
+
const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
25973
|
+
"completed",
|
|
25974
|
+
"failed",
|
|
25975
|
+
"stopped",
|
|
25976
|
+
"cancelled",
|
|
25977
|
+
"interrupted"
|
|
25978
|
+
]);
|
|
25979
|
+
var ThreadBackgroundLivenessService = class extends Context.Service()("@p4code/cli/orchestration/ThreadBackgroundLiveness/ThreadBackgroundLivenessService") {};
|
|
25980
|
+
function make$76() {
|
|
25981
|
+
const stateByThreadId = /* @__PURE__ */ new Map();
|
|
25982
|
+
const stateFor = (threadId) => {
|
|
25983
|
+
const existing = stateByThreadId.get(threadId);
|
|
25984
|
+
if (existing) return existing;
|
|
25985
|
+
const created = {
|
|
25986
|
+
agents: /* @__PURE__ */ new Set(),
|
|
25987
|
+
monitors: /* @__PURE__ */ new Set(),
|
|
25988
|
+
tasks: /* @__PURE__ */ new Map()
|
|
25989
|
+
};
|
|
25990
|
+
stateByThreadId.set(threadId, created);
|
|
25991
|
+
return created;
|
|
25992
|
+
};
|
|
25993
|
+
const drop = (threadId, taskId) => {
|
|
25994
|
+
const state = stateByThreadId.get(threadId);
|
|
25995
|
+
if (!state) return;
|
|
25996
|
+
state.agents.delete(taskId);
|
|
25997
|
+
state.monitors.delete(taskId);
|
|
25998
|
+
if (state.tasks.size === 0) stateByThreadId.delete(threadId);
|
|
25999
|
+
};
|
|
26000
|
+
return {
|
|
26001
|
+
recordTaskLiveness: (input) => {
|
|
26002
|
+
const state = stateFor(input.threadId);
|
|
26003
|
+
const previous = state.tasks.get(input.taskId);
|
|
26004
|
+
const taskType = input.taskType ?? previous?.taskType;
|
|
26005
|
+
const agentId = input.agentId ?? previous?.agentId;
|
|
26006
|
+
if (input.kind === "completed" || input.status !== void 0 && TERMINAL_STATUSES.has(input.status)) {
|
|
26007
|
+
state.tasks.delete(input.taskId);
|
|
26008
|
+
drop(input.threadId, input.taskId);
|
|
26009
|
+
return;
|
|
26010
|
+
}
|
|
26011
|
+
state.tasks.set(input.taskId, {
|
|
26012
|
+
taskType,
|
|
26013
|
+
agentId
|
|
26014
|
+
});
|
|
26015
|
+
drop(input.threadId, input.taskId);
|
|
26016
|
+
if (input.status === "idle") return;
|
|
26017
|
+
if (taskType !== void 0 && INERT_TASK_TYPES.has(taskType)) return;
|
|
26018
|
+
if (agentId !== void 0 && classifyTaskAgentKind({
|
|
26019
|
+
taskType,
|
|
26020
|
+
agentId
|
|
26021
|
+
}) === "background") return;
|
|
26022
|
+
(taskType !== void 0 && MONITOR_TASK_TYPES.has(taskType) ? state.monitors : state.agents).add(input.taskId);
|
|
26023
|
+
},
|
|
26024
|
+
clearThreadLiveness: (threadId) => {
|
|
26025
|
+
stateByThreadId.delete(threadId);
|
|
26026
|
+
},
|
|
26027
|
+
getThreadBackgroundLiveness: (threadId) => {
|
|
26028
|
+
const state = stateByThreadId.get(threadId);
|
|
26029
|
+
if (!state) return null;
|
|
26030
|
+
if (state.agents.size > 0) return "working";
|
|
26031
|
+
if (state.monitors.size > 0) return "monitoring";
|
|
26032
|
+
return null;
|
|
26033
|
+
}
|
|
26034
|
+
};
|
|
26035
|
+
}
|
|
26036
|
+
const layer$64 = Layer.effect(ThreadBackgroundLivenessService, Effect.sync(make$76));
|
|
26037
|
+
//#endregion
|
|
25730
26038
|
//#region ../../packages/shared/src/path.ts
|
|
25731
26039
|
function isWindowsDrivePath(value) {
|
|
25732
26040
|
return /^[a-zA-Z]:([/\\]|$)/.test(value);
|
|
@@ -25805,6 +26113,74 @@ function requireThreadAbsent(input) {
|
|
|
25805
26113
|
return Effect.fail(invariantError(input.command.type, `Thread '${input.threadId}' already exists and cannot be created twice.`));
|
|
25806
26114
|
}
|
|
25807
26115
|
//#endregion
|
|
26116
|
+
//#region src/orchestration/ThreadCompletion.ts
|
|
26117
|
+
const ENGAGEMENT_ACTIVITY_KINDS = /* @__PURE__ */ new Set([
|
|
26118
|
+
"approval.requested",
|
|
26119
|
+
"user-input.requested",
|
|
26120
|
+
"tool.started",
|
|
26121
|
+
"tool.updated",
|
|
26122
|
+
"tool.completed",
|
|
26123
|
+
"task.started",
|
|
26124
|
+
"task.progress",
|
|
26125
|
+
"task.updated",
|
|
26126
|
+
"task.completed",
|
|
26127
|
+
"turn.plan.updated"
|
|
26128
|
+
]);
|
|
26129
|
+
function isThreadEngagement(event) {
|
|
26130
|
+
switch (event.type) {
|
|
26131
|
+
case "thread.message-sent": return "text" in event.payload && typeof event.payload.text === "string" && event.payload.text.length > 0;
|
|
26132
|
+
case "thread.session-set": return "session" in event.payload && (event.payload.session.status === "starting" || event.payload.session.status === "running");
|
|
26133
|
+
case "thread.activity-appended": return "activity" in event.payload && ENGAGEMENT_ACTIVITY_KINDS.has(event.payload.activity.kind);
|
|
26134
|
+
case "thread.proposed-plan-upserted":
|
|
26135
|
+
case "thread.pinned": return true;
|
|
26136
|
+
default: return false;
|
|
26137
|
+
}
|
|
26138
|
+
}
|
|
26139
|
+
function completionState(thread) {
|
|
26140
|
+
return {
|
|
26141
|
+
lifecycle: thread.lifecycle ?? (thread.archivedAt !== null ? "archived" : thread.settledOverride === "settled" ? "done" : "active"),
|
|
26142
|
+
lifecycleReason: thread.lifecycleReason ?? (thread.settledOverride === "settled" ? "manual" : "created"),
|
|
26143
|
+
lifecycleChangedAt: thread.lifecycleChangedAt ?? thread.archivedAt ?? thread.settledAt ?? thread.createdAt,
|
|
26144
|
+
lastEngagedAt: thread.lastEngagedAt ?? thread.createdAt,
|
|
26145
|
+
doneAt: thread.doneAt ?? thread.settledAt
|
|
26146
|
+
};
|
|
26147
|
+
}
|
|
26148
|
+
/** Transition metadata is shared by in-memory and persisted projections. */
|
|
26149
|
+
function completionAfterEvent(thread, event) {
|
|
26150
|
+
const state = completionState(thread);
|
|
26151
|
+
if (isThreadEngagement(event)) state.lastEngagedAt = state.lastEngagedAt > event.occurredAt ? state.lastEngagedAt : event.occurredAt;
|
|
26152
|
+
switch (event.type) {
|
|
26153
|
+
case "thread.settled": return {
|
|
26154
|
+
...state,
|
|
26155
|
+
lifecycle: "done",
|
|
26156
|
+
doneAt: event.payload.settledAt,
|
|
26157
|
+
lifecycleReason: event.payload.lifecycleReason ?? "manual",
|
|
26158
|
+
lifecycleChangedAt: event.payload.lifecycleChangedAt ?? event.payload.settledAt
|
|
26159
|
+
};
|
|
26160
|
+
case "thread.unsettled": return {
|
|
26161
|
+
...state,
|
|
26162
|
+
lifecycle: "active",
|
|
26163
|
+
doneAt: null,
|
|
26164
|
+
lifecycleReason: event.payload.lifecycleReason ?? event.payload.reason,
|
|
26165
|
+
lifecycleChangedAt: event.payload.lifecycleChangedAt ?? event.payload.updatedAt,
|
|
26166
|
+
lastEngagedAt: event.payload.lastEngagedAt ?? (state.lastEngagedAt > event.payload.updatedAt ? state.lastEngagedAt : event.payload.updatedAt)
|
|
26167
|
+
};
|
|
26168
|
+
case "thread.archived": return {
|
|
26169
|
+
...state,
|
|
26170
|
+
lifecycle: "archived",
|
|
26171
|
+
lifecycleReason: "archive",
|
|
26172
|
+
lifecycleChangedAt: event.payload.lifecycleChangedAt ?? event.payload.archivedAt
|
|
26173
|
+
};
|
|
26174
|
+
case "thread.unarchived": return {
|
|
26175
|
+
...state,
|
|
26176
|
+
lifecycle: state.doneAt !== null ? "done" : "active",
|
|
26177
|
+
lifecycleReason: "restore",
|
|
26178
|
+
lifecycleChangedAt: event.payload.lifecycleChangedAt ?? event.payload.updatedAt
|
|
26179
|
+
};
|
|
26180
|
+
default: return state;
|
|
26181
|
+
}
|
|
26182
|
+
}
|
|
26183
|
+
//#endregion
|
|
25808
26184
|
//#region src/attachmentPaths.ts
|
|
25809
26185
|
function normalizeAttachmentRelativePath(rawRelativePath) {
|
|
25810
26186
|
const normalized = NodePath.normalize(rawRelativePath).replace(/^[/\\]+/, "");
|
|
@@ -26220,6 +26596,10 @@ function createEmptyReadModel(nowIso) {
|
|
|
26220
26596
|
function projectEvent(model, event) {
|
|
26221
26597
|
const nextBase = {
|
|
26222
26598
|
...model,
|
|
26599
|
+
threads: event.aggregateKind !== "thread" ? model.threads : model.threads.map((thread) => thread.id === event.aggregateId ? {
|
|
26600
|
+
...thread,
|
|
26601
|
+
...completionAfterEvent(thread, event)
|
|
26602
|
+
} : thread),
|
|
26223
26603
|
snapshotSequence: event.sequence,
|
|
26224
26604
|
updatedAt: event.occurredAt
|
|
26225
26605
|
};
|
|
@@ -26327,8 +26707,13 @@ function projectEvent(model, event) {
|
|
|
26327
26707
|
latestTurn: null,
|
|
26328
26708
|
createdAt: payload.createdAt,
|
|
26329
26709
|
updatedAt: payload.updatedAt,
|
|
26710
|
+
lifecycle: "active",
|
|
26711
|
+
lifecycleReason: "created",
|
|
26712
|
+
lifecycleChangedAt: payload.createdAt,
|
|
26713
|
+
lastEngagedAt: payload.createdAt,
|
|
26714
|
+
doneAt: null,
|
|
26715
|
+
settledOverride: "active",
|
|
26330
26716
|
archivedAt: null,
|
|
26331
|
-
settledOverride: null,
|
|
26332
26717
|
settledAt: null,
|
|
26333
26718
|
snoozedUntil: null,
|
|
26334
26719
|
snoozedAt: null,
|
|
@@ -26376,7 +26761,7 @@ function projectEvent(model, event) {
|
|
|
26376
26761
|
case "thread.unsettled": return decodeForEvent(ThreadUnsettledPayload, event.payload, event.type, "payload").pipe(Effect.map((payload) => ({
|
|
26377
26762
|
...nextBase,
|
|
26378
26763
|
threads: updateThread(nextBase.threads, payload.threadId, {
|
|
26379
|
-
settledOverride:
|
|
26764
|
+
settledOverride: "active",
|
|
26380
26765
|
settledAt: null,
|
|
26381
26766
|
updatedAt: payload.updatedAt
|
|
26382
26767
|
})
|
|
@@ -26736,7 +27121,7 @@ const decideCommandSequence = Effect.fn("decideCommandSequence")(function* ({ co
|
|
|
26736
27121
|
}
|
|
26737
27122
|
return plannedEvents;
|
|
26738
27123
|
});
|
|
26739
|
-
const
|
|
27124
|
+
const decideCommand = Effect.fn("decideCommand")(function* ({ command, readModel }) {
|
|
26740
27125
|
switch (command.type) {
|
|
26741
27126
|
case "project.create":
|
|
26742
27127
|
yield* requireProjectAbsent({
|
|
@@ -27376,12 +27761,19 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
27376
27761
|
}
|
|
27377
27762
|
return events;
|
|
27378
27763
|
}
|
|
27764
|
+
case "thread.complete":
|
|
27765
|
+
case "thread.complete.auto":
|
|
27379
27766
|
case "thread.settle": {
|
|
27380
27767
|
const thread = yield* requireThreadNotArchived({
|
|
27381
27768
|
readModel,
|
|
27382
27769
|
command,
|
|
27383
27770
|
threadId: command.threadId
|
|
27384
27771
|
});
|
|
27772
|
+
const occurredAt = yield* nowIso$8;
|
|
27773
|
+
if (command.type === "thread.complete.auto" && (completionState(thread).lastEngagedAt !== command.expectedLastEngagedAt || !(Date.parse(command.expectedLastEngagedAt) < Date.parse(command.eligibleAt)) || !(Date.parse(command.eligibleAt) <= Date.parse(occurredAt)) || thread.pinnedAt != null)) return yield* new OrchestrationCommandInvariantError({
|
|
27774
|
+
commandType: command.type,
|
|
27775
|
+
detail: "Thread engagement changed or automatic completion is no longer eligible"
|
|
27776
|
+
});
|
|
27385
27777
|
if (thread.session?.status === "starting" || thread.session?.status === "running") return yield* new OrchestrationCommandInvariantError({
|
|
27386
27778
|
commandType: command.type,
|
|
27387
27779
|
detail: `thread ${command.threadId} has an active session and cannot be settled`
|
|
@@ -27390,7 +27782,6 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
27390
27782
|
commandType: command.type,
|
|
27391
27783
|
detail: `thread ${command.threadId} has a pending approval or user-input request and cannot be settled`
|
|
27392
27784
|
});
|
|
27393
|
-
const occurredAt = yield* nowIso$8;
|
|
27394
27785
|
if (threadHasQueuedTurnStart(thread, occurredAt)) return yield* new OrchestrationCommandInvariantError({
|
|
27395
27786
|
commandType: command.type,
|
|
27396
27787
|
detail: `thread ${command.threadId} has a queued turn start and cannot be settled`
|
|
@@ -27425,6 +27816,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
27425
27816
|
}
|
|
27426
27817
|
}];
|
|
27427
27818
|
}
|
|
27819
|
+
case "thread.reopen":
|
|
27428
27820
|
case "thread.unsettle": {
|
|
27429
27821
|
const thread = yield* requireThreadNotArchived({
|
|
27430
27822
|
readModel,
|
|
@@ -27443,7 +27835,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
27443
27835
|
type: "thread.unsettled",
|
|
27444
27836
|
payload: {
|
|
27445
27837
|
threadId: command.threadId,
|
|
27446
|
-
reason:
|
|
27838
|
+
reason: "user",
|
|
27447
27839
|
updatedAt: alreadyPinnedActive ? thread.updatedAt : occurredAt
|
|
27448
27840
|
}
|
|
27449
27841
|
};
|
|
@@ -27800,7 +28192,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
27800
28192
|
}
|
|
27801
28193
|
};
|
|
27802
28194
|
const lifecycleResetEvents = [];
|
|
27803
|
-
if (targetThread.settledOverride
|
|
28195
|
+
if (targetThread.settledOverride === "settled") lifecycleResetEvents.push({
|
|
27804
28196
|
...yield* withEventBase({
|
|
27805
28197
|
aggregateKind: "thread",
|
|
27806
28198
|
aggregateId: command.threadId,
|
|
@@ -28051,7 +28443,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
28051
28443
|
}
|
|
28052
28444
|
};
|
|
28053
28445
|
const isSessionActivity = command.session.status === "starting" || command.session.status === "running";
|
|
28054
|
-
if (thread.settledOverride
|
|
28446
|
+
if (thread.settledOverride !== "settled" || !isSessionActivity) return sessionSetEvent;
|
|
28055
28447
|
return [{
|
|
28056
28448
|
...yield* withEventBase({
|
|
28057
28449
|
aggregateKind: "thread",
|
|
@@ -28202,7 +28594,7 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
28202
28594
|
}
|
|
28203
28595
|
};
|
|
28204
28596
|
const wakesSettledThread = command.activity.kind === "approval.requested" || command.activity.kind === "user-input.requested";
|
|
28205
|
-
if (thread.settledOverride
|
|
28597
|
+
if (thread.settledOverride !== "settled" || !wakesSettledThread) return activityAppendedEvent;
|
|
28206
28598
|
return [{
|
|
28207
28599
|
...yield* withEventBase({
|
|
28208
28600
|
aggregateKind: "thread",
|
|
@@ -28227,6 +28619,74 @@ const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(funct
|
|
|
28227
28619
|
}
|
|
28228
28620
|
}
|
|
28229
28621
|
});
|
|
28622
|
+
const decideOrchestrationCommand = Effect.fn("decideOrchestrationCommand")(function* (input) {
|
|
28623
|
+
const { command, readModel } = input;
|
|
28624
|
+
if (input.hasLiveBackgroundWork && (command.type === "thread.settle" || command.type === "thread.complete" || command.type === "thread.complete.auto")) return yield* new OrchestrationCommandInvariantError({
|
|
28625
|
+
commandType: command.type,
|
|
28626
|
+
detail: "Thread has live background work and cannot be completed"
|
|
28627
|
+
});
|
|
28628
|
+
const decided = yield* decideCommand(input);
|
|
28629
|
+
const events = Array.isArray(decided) ? [...decided] : [decided];
|
|
28630
|
+
const target = "threadId" in command ? readModel.threads.find((thread) => thread.id === command.threadId) : void 0;
|
|
28631
|
+
const engagement = events.find(isThreadEngagement);
|
|
28632
|
+
if (target && target.archivedAt === null && completionState(target).lifecycle === "done" && engagement && !events.some((event) => event.type === "thread.unsettled")) events.unshift({
|
|
28633
|
+
...yield* withEventBase({
|
|
28634
|
+
aggregateKind: "thread",
|
|
28635
|
+
aggregateId: target.id,
|
|
28636
|
+
occurredAt: engagement.occurredAt,
|
|
28637
|
+
commandId: command.commandId
|
|
28638
|
+
}),
|
|
28639
|
+
type: "thread.unsettled",
|
|
28640
|
+
payload: {
|
|
28641
|
+
threadId: target.id,
|
|
28642
|
+
reason: "activity",
|
|
28643
|
+
updatedAt: engagement.occurredAt
|
|
28644
|
+
}
|
|
28645
|
+
});
|
|
28646
|
+
return events.map((event) => {
|
|
28647
|
+
if (event.type === "thread.created") return {
|
|
28648
|
+
...event,
|
|
28649
|
+
payload: {
|
|
28650
|
+
...event.payload,
|
|
28651
|
+
lifecycle: "active",
|
|
28652
|
+
lifecycleReason: "created",
|
|
28653
|
+
lifecycleChangedAt: event.payload.createdAt,
|
|
28654
|
+
lastEngagedAt: event.payload.createdAt,
|
|
28655
|
+
doneAt: null
|
|
28656
|
+
}
|
|
28657
|
+
};
|
|
28658
|
+
const eventThread = readModel.threads.find((thread) => thread.id === event.aggregateId);
|
|
28659
|
+
if (!eventThread) return event;
|
|
28660
|
+
switch (event.type) {
|
|
28661
|
+
case "thread.settled":
|
|
28662
|
+
case "thread.unsettled":
|
|
28663
|
+
case "thread.archived":
|
|
28664
|
+
case "thread.unarchived": {
|
|
28665
|
+
const previous = completionState(eventThread);
|
|
28666
|
+
const state = completionAfterEvent(eventThread, {
|
|
28667
|
+
...event,
|
|
28668
|
+
sequence: readModel.snapshotSequence + 1
|
|
28669
|
+
});
|
|
28670
|
+
if (event.type === "thread.settled") state.lifecycleReason = previous.lifecycle === "done" ? previous.lifecycleReason : command.type === "thread.complete.auto" ? command.reason : "manual";
|
|
28671
|
+
if (event.type === "thread.settled" && previous.lifecycle === "done" || event.type === "thread.unsettled" && previous.lifecycle === "active" && (command.type === "thread.reopen" || command.type === "thread.unsettle")) return {
|
|
28672
|
+
...event,
|
|
28673
|
+
payload: {
|
|
28674
|
+
...event.payload,
|
|
28675
|
+
...previous
|
|
28676
|
+
}
|
|
28677
|
+
};
|
|
28678
|
+
return {
|
|
28679
|
+
...event,
|
|
28680
|
+
payload: {
|
|
28681
|
+
...event.payload,
|
|
28682
|
+
...state
|
|
28683
|
+
}
|
|
28684
|
+
};
|
|
28685
|
+
}
|
|
28686
|
+
default: return event;
|
|
28687
|
+
}
|
|
28688
|
+
});
|
|
28689
|
+
});
|
|
28230
28690
|
//#endregion
|
|
28231
28691
|
//#region src/orchestration/Services/ProjectionPipeline.ts
|
|
28232
28692
|
/**
|
|
@@ -28267,6 +28727,7 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
28267
28727
|
const projectionPipeline = yield* OrchestrationProjectionPipeline;
|
|
28268
28728
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
28269
28729
|
const crypto = yield* Crypto.Crypto;
|
|
28730
|
+
const backgroundLiveness = yield* ThreadBackgroundLivenessService;
|
|
28270
28731
|
const nowIso = Effect.map(DateTime.now, DateTime.formatIso);
|
|
28271
28732
|
let commandReadModel = createEmptyReadModel(yield* nowIso);
|
|
28272
28733
|
const commandQueue = yield* Queue.unbounded();
|
|
@@ -28314,7 +28775,8 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
28314
28775
|
}
|
|
28315
28776
|
const eventBase = yield* decideOrchestrationCommand({
|
|
28316
28777
|
command: envelope.command,
|
|
28317
|
-
readModel: commandReadModel
|
|
28778
|
+
readModel: commandReadModel,
|
|
28779
|
+
hasLiveBackgroundWork: "threadId" in envelope.command && backgroundLiveness.getThreadBackgroundLiveness(envelope.command.threadId) !== null
|
|
28318
28780
|
}).pipe(Effect.provideService(Crypto.Crypto, crypto), Effect.mapError((cause) => isOrchestrationCommandInvariantError(cause) ? cause : new OrchestrationCommandInvariantError({
|
|
28319
28781
|
commandType: envelope.command.type,
|
|
28320
28782
|
detail: "Failed to generate an event identifier.",
|
|
@@ -28416,7 +28878,7 @@ const makeOrchestrationEngine = Effect.gen(function* () {
|
|
|
28416
28878
|
latestSequence: Effect.sync(() => commandReadModel.snapshotSequence)
|
|
28417
28879
|
};
|
|
28418
28880
|
});
|
|
28419
|
-
const OrchestrationEngineLive = Layer.effect(OrchestrationEngineService, makeOrchestrationEngine);
|
|
28881
|
+
const OrchestrationEngineLive = Layer.effect(OrchestrationEngineService, makeOrchestrationEngine).pipe(Layer.provide(layer$64));
|
|
28420
28882
|
//#endregion
|
|
28421
28883
|
//#region src/persistence/Services/ProjectionPendingApprovals.ts
|
|
28422
28884
|
/**
|
|
@@ -28682,6 +29144,7 @@ var ProjectionTurnRepository = class extends Context.Service()("@p4code/cli/pers
|
|
|
28682
29144
|
* @module ProjectionThreadRepository
|
|
28683
29145
|
*/
|
|
28684
29146
|
const ProjectionThread = Schema$1.Struct({
|
|
29147
|
+
...ThreadCompletionFields,
|
|
28685
29148
|
threadId: ThreadId,
|
|
28686
29149
|
projectId: ProjectId,
|
|
28687
29150
|
title: Schema$1.String,
|
|
@@ -29684,6 +30147,10 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29684
30147
|
archived_at,
|
|
29685
30148
|
settled_override,
|
|
29686
30149
|
settled_at,
|
|
30150
|
+
lifecycle,
|
|
30151
|
+
lifecycle_reason,
|
|
30152
|
+
lifecycle_changed_at,
|
|
30153
|
+
last_engaged_at,
|
|
29687
30154
|
snoozed_until,
|
|
29688
30155
|
snoozed_at,
|
|
29689
30156
|
pinned_at,
|
|
@@ -29714,6 +30181,10 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29714
30181
|
${row.archivedAt},
|
|
29715
30182
|
${row.settledOverride},
|
|
29716
30183
|
${row.settledAt},
|
|
30184
|
+
${row.lifecycle ?? (row.archivedAt !== null ? "archived" : row.settledOverride === "settled" ? "done" : "active")},
|
|
30185
|
+
${row.lifecycleReason ?? (row.settledOverride === "settled" ? "manual" : "created")},
|
|
30186
|
+
${row.lifecycleChangedAt ?? row.settledAt ?? row.createdAt},
|
|
30187
|
+
${row.lastEngagedAt ?? row.latestUserMessageAt ?? row.createdAt},
|
|
29717
30188
|
${row.snoozedUntil},
|
|
29718
30189
|
${row.snoozedAt},
|
|
29719
30190
|
${row.pinnedAt},
|
|
@@ -29744,6 +30215,10 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29744
30215
|
archived_at = excluded.archived_at,
|
|
29745
30216
|
settled_override = excluded.settled_override,
|
|
29746
30217
|
settled_at = excluded.settled_at,
|
|
30218
|
+
lifecycle = excluded.lifecycle,
|
|
30219
|
+
lifecycle_reason = excluded.lifecycle_reason,
|
|
30220
|
+
lifecycle_changed_at = excluded.lifecycle_changed_at,
|
|
30221
|
+
last_engaged_at = excluded.last_engaged_at,
|
|
29747
30222
|
snoozed_until = excluded.snoozed_until,
|
|
29748
30223
|
snoozed_at = excluded.snoozed_at,
|
|
29749
30224
|
pinned_at = excluded.pinned_at,
|
|
@@ -29779,6 +30254,10 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29779
30254
|
archived_at AS "archivedAt",
|
|
29780
30255
|
settled_override AS "settledOverride",
|
|
29781
30256
|
settled_at AS "settledAt",
|
|
30257
|
+
lifecycle AS "lifecycle",
|
|
30258
|
+
lifecycle_reason AS "lifecycleReason",
|
|
30259
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
30260
|
+
last_engaged_at AS "lastEngagedAt",
|
|
29782
30261
|
snoozed_until AS "snoozedUntil",
|
|
29783
30262
|
snoozed_at AS "snoozedAt",
|
|
29784
30263
|
pinned_at AS "pinnedAt",
|
|
@@ -29816,6 +30295,10 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29816
30295
|
archived_at AS "archivedAt",
|
|
29817
30296
|
settled_override AS "settledOverride",
|
|
29818
30297
|
settled_at AS "settledAt",
|
|
30298
|
+
lifecycle AS "lifecycle",
|
|
30299
|
+
lifecycle_reason AS "lifecycleReason",
|
|
30300
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
30301
|
+
last_engaged_at AS "lastEngagedAt",
|
|
29819
30302
|
snoozed_until AS "snoozedUntil",
|
|
29820
30303
|
snoozed_at AS "snoozedAt",
|
|
29821
30304
|
pinned_at AS "pinnedAt",
|
|
@@ -29853,6 +30336,14 @@ const makeProjectionThreadRepository = Effect.gen(function* () {
|
|
|
29853
30336
|
const ProjectionThreadRepositoryLive = Layer.effect(ProjectionThreadRepository, makeProjectionThreadRepository);
|
|
29854
30337
|
//#endregion
|
|
29855
30338
|
//#region src/orchestration/Layers/ProjectionPipeline.ts
|
|
30339
|
+
/**
|
|
30340
|
+
* Tasks the agent started that never reported a terminal status. A task that
|
|
30341
|
+
* outlives its turn is the case worth surfacing: the session goes back to idle
|
|
30342
|
+
* while the task keeps running, so nothing else in the shell shows the work.
|
|
30343
|
+
*
|
|
30344
|
+
* Counted rather than flagged so a lost completion can only strand one task,
|
|
30345
|
+
* and read as a boolean by the shell.
|
|
30346
|
+
*/
|
|
29856
30347
|
const ORCHESTRATION_PROJECTOR_NAMES = {
|
|
29857
30348
|
projects: "projection.projects",
|
|
29858
30349
|
threads: "projection.threads",
|
|
@@ -29898,14 +30389,6 @@ function extractActivityTaskId(payload) {
|
|
|
29898
30389
|
const taskId = payload.taskId;
|
|
29899
30390
|
return typeof taskId === "string" && taskId.length > 0 ? taskId : null;
|
|
29900
30391
|
}
|
|
29901
|
-
/**
|
|
29902
|
-
* Tasks the agent started that never reported a terminal status. A task that
|
|
29903
|
-
* outlives its turn is the case worth surfacing: the session goes back to idle
|
|
29904
|
-
* while the task keeps running, so nothing else in the shell shows the work.
|
|
29905
|
-
*
|
|
29906
|
-
* Counted rather than flagged so a lost completion can only strand one task,
|
|
29907
|
-
* and read as a boolean by the shell.
|
|
29908
|
-
*/
|
|
29909
30392
|
function deriveBackgroundTaskCountFromActivities(activities) {
|
|
29910
30393
|
const openTaskIds = /* @__PURE__ */ new Set();
|
|
29911
30394
|
const ordered = [...activities].toSorted((left, right) => left.createdAt.localeCompare(right.createdAt) || left.activityId.localeCompare(right.activityId));
|
|
@@ -30248,7 +30731,12 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30248
30731
|
createdAt: event.payload.createdAt,
|
|
30249
30732
|
updatedAt: event.payload.updatedAt,
|
|
30250
30733
|
archivedAt: null,
|
|
30251
|
-
|
|
30734
|
+
lifecycle: "active",
|
|
30735
|
+
lifecycleReason: "created",
|
|
30736
|
+
lifecycleChangedAt: event.payload.createdAt,
|
|
30737
|
+
lastEngagedAt: event.payload.createdAt,
|
|
30738
|
+
doneAt: null,
|
|
30739
|
+
settledOverride: "active",
|
|
30252
30740
|
settledAt: null,
|
|
30253
30741
|
snoozedUntil: null,
|
|
30254
30742
|
snoozedAt: null,
|
|
@@ -30268,6 +30756,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30268
30756
|
if (Option.isNone(existingRow)) return;
|
|
30269
30757
|
yield* projectionThreadRepository.upsert({
|
|
30270
30758
|
...existingRow.value,
|
|
30759
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30271
30760
|
archivedAt: event.payload.archivedAt,
|
|
30272
30761
|
updatedAt: event.payload.updatedAt
|
|
30273
30762
|
});
|
|
@@ -30278,6 +30767,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30278
30767
|
if (Option.isNone(existingRow)) return;
|
|
30279
30768
|
yield* projectionThreadRepository.upsert({
|
|
30280
30769
|
...existingRow.value,
|
|
30770
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30281
30771
|
archivedAt: null,
|
|
30282
30772
|
updatedAt: event.payload.updatedAt
|
|
30283
30773
|
});
|
|
@@ -30288,6 +30778,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30288
30778
|
if (Option.isNone(existingRow)) return;
|
|
30289
30779
|
yield* projectionThreadRepository.upsert({
|
|
30290
30780
|
...existingRow.value,
|
|
30781
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30291
30782
|
settledOverride: "settled",
|
|
30292
30783
|
settledAt: event.payload.settledAt,
|
|
30293
30784
|
updatedAt: event.payload.updatedAt
|
|
@@ -30299,7 +30790,8 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30299
30790
|
if (Option.isNone(existingRow)) return;
|
|
30300
30791
|
yield* projectionThreadRepository.upsert({
|
|
30301
30792
|
...existingRow.value,
|
|
30302
|
-
|
|
30793
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30794
|
+
settledOverride: "active",
|
|
30303
30795
|
settledAt: null,
|
|
30304
30796
|
updatedAt: event.payload.updatedAt
|
|
30305
30797
|
});
|
|
@@ -30310,6 +30802,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30310
30802
|
if (Option.isNone(existingRow)) return;
|
|
30311
30803
|
yield* projectionThreadRepository.upsert({
|
|
30312
30804
|
...existingRow.value,
|
|
30805
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30313
30806
|
snoozedUntil: event.payload.snoozedUntil,
|
|
30314
30807
|
snoozedAt: event.payload.snoozedAt,
|
|
30315
30808
|
updatedAt: event.payload.updatedAt
|
|
@@ -30321,6 +30814,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30321
30814
|
if (Option.isNone(existingRow)) return;
|
|
30322
30815
|
yield* projectionThreadRepository.upsert({
|
|
30323
30816
|
...existingRow.value,
|
|
30817
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30324
30818
|
snoozedUntil: null,
|
|
30325
30819
|
snoozedAt: null,
|
|
30326
30820
|
updatedAt: event.payload.updatedAt
|
|
@@ -30332,6 +30826,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30332
30826
|
if (Option.isNone(existingRow)) return;
|
|
30333
30827
|
yield* projectionThreadRepository.upsert({
|
|
30334
30828
|
...existingRow.value,
|
|
30829
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30335
30830
|
pinnedAt: event.payload.pinnedAt,
|
|
30336
30831
|
...event.payload.pinOrderKey === void 0 ? {} : { pinOrderKey: event.payload.pinOrderKey },
|
|
30337
30832
|
updatedAt: event.payload.updatedAt
|
|
@@ -30343,6 +30838,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30343
30838
|
if (Option.isNone(existingRow)) return;
|
|
30344
30839
|
yield* projectionThreadRepository.upsert({
|
|
30345
30840
|
...existingRow.value,
|
|
30841
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30346
30842
|
pinnedAt: null,
|
|
30347
30843
|
pinOrderKey: null,
|
|
30348
30844
|
updatedAt: event.payload.updatedAt
|
|
@@ -30354,6 +30850,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30354
30850
|
if (Option.isNone(existingRow)) return;
|
|
30355
30851
|
yield* projectionThreadRepository.upsert({
|
|
30356
30852
|
...existingRow.value,
|
|
30853
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30357
30854
|
pinOrderKey: event.payload.pinOrderKey,
|
|
30358
30855
|
updatedAt: event.payload.updatedAt
|
|
30359
30856
|
});
|
|
@@ -30364,6 +30861,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30364
30861
|
if (Option.isNone(existingRow)) return;
|
|
30365
30862
|
yield* projectionThreadRepository.upsert({
|
|
30366
30863
|
...existingRow.value,
|
|
30864
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30367
30865
|
...event.payload.title !== void 0 ? { title: event.payload.title } : {},
|
|
30368
30866
|
...event.payload.modelSelection !== void 0 ? { modelSelection: event.payload.modelSelection } : {},
|
|
30369
30867
|
...event.payload.branch !== void 0 ? { branch: event.payload.branch } : {},
|
|
@@ -30378,6 +30876,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30378
30876
|
if (Option.isNone(existingRow)) return;
|
|
30379
30877
|
yield* projectionThreadRepository.upsert({
|
|
30380
30878
|
...existingRow.value,
|
|
30879
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30381
30880
|
runtimeMode: event.payload.runtimeMode,
|
|
30382
30881
|
updatedAt: event.payload.updatedAt
|
|
30383
30882
|
});
|
|
@@ -30388,6 +30887,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30388
30887
|
if (Option.isNone(existingRow)) return;
|
|
30389
30888
|
yield* projectionThreadRepository.upsert({
|
|
30390
30889
|
...existingRow.value,
|
|
30890
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30391
30891
|
interactionMode: event.payload.interactionMode,
|
|
30392
30892
|
updatedAt: event.payload.updatedAt
|
|
30393
30893
|
});
|
|
@@ -30398,6 +30898,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30398
30898
|
if (Option.isNone(existingRow)) return;
|
|
30399
30899
|
yield* projectionThreadRepository.upsert({
|
|
30400
30900
|
...existingRow.value,
|
|
30901
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30401
30902
|
compressMode: event.payload.compressMode,
|
|
30402
30903
|
updatedAt: event.payload.updatedAt
|
|
30403
30904
|
});
|
|
@@ -30408,6 +30909,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30408
30909
|
if (Option.isNone(existingRow)) return;
|
|
30409
30910
|
yield* projectionThreadRepository.upsert({
|
|
30410
30911
|
...existingRow.value,
|
|
30912
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30411
30913
|
unpromptedSubagents: event.payload.unpromptedSubagents ? 1 : 0,
|
|
30412
30914
|
updatedAt: event.payload.updatedAt
|
|
30413
30915
|
});
|
|
@@ -30419,6 +30921,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30419
30921
|
if (Option.isNone(existingRow)) return;
|
|
30420
30922
|
yield* projectionThreadRepository.upsert({
|
|
30421
30923
|
...existingRow.value,
|
|
30924
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30422
30925
|
deletedAt: event.payload.deletedAt,
|
|
30423
30926
|
updatedAt: event.payload.deletedAt
|
|
30424
30927
|
});
|
|
@@ -30433,6 +30936,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30433
30936
|
if (Option.isNone(existingRow)) return;
|
|
30434
30937
|
yield* projectionThreadRepository.upsert({
|
|
30435
30938
|
...existingRow.value,
|
|
30939
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30436
30940
|
updatedAt: event.occurredAt
|
|
30437
30941
|
});
|
|
30438
30942
|
yield* refreshThreadShellSummary(event.payload.threadId);
|
|
@@ -30443,6 +30947,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30443
30947
|
if (Option.isNone(existingRow)) return;
|
|
30444
30948
|
yield* projectionThreadRepository.upsert({
|
|
30445
30949
|
...existingRow.value,
|
|
30950
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30446
30951
|
latestTurnId: event.payload.session.activeTurnId,
|
|
30447
30952
|
updatedAt: event.occurredAt
|
|
30448
30953
|
});
|
|
@@ -30454,6 +30959,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30454
30959
|
if (Option.isNone(existingRow)) return;
|
|
30455
30960
|
yield* projectionThreadRepository.upsert({
|
|
30456
30961
|
...existingRow.value,
|
|
30962
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30457
30963
|
latestTurnId: event.payload.turnId,
|
|
30458
30964
|
updatedAt: event.occurredAt
|
|
30459
30965
|
});
|
|
@@ -30476,6 +30982,7 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
30476
30982
|
}
|
|
30477
30983
|
yield* projectionThreadRepository.upsert({
|
|
30478
30984
|
...existingRow.value,
|
|
30985
|
+
...completionAfterEvent(existingRow.value, event),
|
|
30479
30986
|
latestTurnId,
|
|
30480
30987
|
updatedAt: event.occurredAt
|
|
30481
30988
|
});
|
|
@@ -31002,84 +31509,6 @@ const makeOrchestrationProjectionPipeline = Effect.fn("makeOrchestrationProjecti
|
|
|
31002
31509
|
});
|
|
31003
31510
|
const OrchestrationProjectionPipelineLive = Layer.effect(OrchestrationProjectionPipeline, makeOrchestrationProjectionPipeline()).pipe(Layer.provideMerge(ProjectionProjectRepositoryLive), Layer.provideMerge(ProjectionThreadRepositoryLive), Layer.provideMerge(ProjectionThreadMessageRepositoryLive), Layer.provideMerge(ProjectionThreadProposedPlanRepositoryLive), Layer.provideMerge(ProjectionThreadScheduledTaskRepositoryLive), Layer.provideMerge(ProjectionThreadActivityRepositoryLive), Layer.provideMerge(ProjectionThreadSessionRepositoryLive), Layer.provideMerge(ProjectionTurnRepositoryLive), Layer.provideMerge(ProjectionPendingApprovalRepositoryLive), Layer.provideMerge(ProjectionStateRepositoryLive));
|
|
31004
31511
|
//#endregion
|
|
31005
|
-
//#region src/orchestration/ThreadBackgroundLiveness.ts
|
|
31006
|
-
/**
|
|
31007
|
-
* ThreadBackgroundLivenessService - in-memory per-thread background liveness
|
|
31008
|
-
* for the sidebar status pill.
|
|
31009
|
-
*
|
|
31010
|
-
* The turn can settle while native background work runs on (subagent fleets,
|
|
31011
|
-
* workflow runs, Monitor watch loops); the shell previously showed nothing.
|
|
31012
|
-
* Ingestion records task lifecycle transitions and the shell query reads the
|
|
31013
|
-
* derived state at mapping time — no persistence, no migration. After a
|
|
31014
|
-
* server restart the registry is empty until new task events arrive, which
|
|
31015
|
-
* matches reality: orphaned background work is not live.
|
|
31016
|
-
*
|
|
31017
|
-
* "monitoring" is reserved for watch loops (monitor tasks and background
|
|
31018
|
-
* shells) when they are the ONLY live work; any agent work presents as
|
|
31019
|
-
* "working".
|
|
31020
|
-
*
|
|
31021
|
-
* @module ThreadBackgroundLivenessService
|
|
31022
|
-
*/
|
|
31023
|
-
const TERMINAL_STATUSES = /* @__PURE__ */ new Set([
|
|
31024
|
-
"completed",
|
|
31025
|
-
"failed",
|
|
31026
|
-
"stopped",
|
|
31027
|
-
"cancelled",
|
|
31028
|
-
"interrupted"
|
|
31029
|
-
]);
|
|
31030
|
-
var ThreadBackgroundLivenessService = class extends Context.Service()("@p4code/cli/orchestration/ThreadBackgroundLiveness/ThreadBackgroundLivenessService") {};
|
|
31031
|
-
function make$75() {
|
|
31032
|
-
const stateByThreadId = /* @__PURE__ */ new Map();
|
|
31033
|
-
const stateFor = (threadId) => {
|
|
31034
|
-
const existing = stateByThreadId.get(threadId);
|
|
31035
|
-
if (existing) return existing;
|
|
31036
|
-
const created = {
|
|
31037
|
-
agents: /* @__PURE__ */ new Set(),
|
|
31038
|
-
monitors: /* @__PURE__ */ new Set()
|
|
31039
|
-
};
|
|
31040
|
-
stateByThreadId.set(threadId, created);
|
|
31041
|
-
return created;
|
|
31042
|
-
};
|
|
31043
|
-
const drop = (threadId, taskId) => {
|
|
31044
|
-
const state = stateByThreadId.get(threadId);
|
|
31045
|
-
if (!state) return;
|
|
31046
|
-
state.agents.delete(taskId);
|
|
31047
|
-
state.monitors.delete(taskId);
|
|
31048
|
-
if (state.agents.size === 0 && state.monitors.size === 0) stateByThreadId.delete(threadId);
|
|
31049
|
-
};
|
|
31050
|
-
return {
|
|
31051
|
-
recordTaskLiveness: (input) => {
|
|
31052
|
-
const taskType = input.taskType;
|
|
31053
|
-
if (taskType !== void 0 && INERT_TASK_TYPES.has(taskType)) {
|
|
31054
|
-
drop(input.threadId, input.taskId);
|
|
31055
|
-
return;
|
|
31056
|
-
}
|
|
31057
|
-
if (input.agentId !== void 0 && (taskType === void 0 || MONITOR_TASK_TYPES.has(taskType))) {
|
|
31058
|
-
drop(input.threadId, input.taskId);
|
|
31059
|
-
return;
|
|
31060
|
-
}
|
|
31061
|
-
if (input.kind === "completed" || input.status === "idle" || input.status !== void 0 && TERMINAL_STATUSES.has(input.status)) {
|
|
31062
|
-
drop(input.threadId, input.taskId);
|
|
31063
|
-
return;
|
|
31064
|
-
}
|
|
31065
|
-
drop(input.threadId, input.taskId);
|
|
31066
|
-
const state = stateFor(input.threadId);
|
|
31067
|
-
(taskType !== void 0 && MONITOR_TASK_TYPES.has(taskType) ? state.monitors : state.agents).add(input.taskId);
|
|
31068
|
-
},
|
|
31069
|
-
clearThreadLiveness: (threadId) => {
|
|
31070
|
-
stateByThreadId.delete(threadId);
|
|
31071
|
-
},
|
|
31072
|
-
getThreadBackgroundLiveness: (threadId) => {
|
|
31073
|
-
const state = stateByThreadId.get(threadId);
|
|
31074
|
-
if (!state) return null;
|
|
31075
|
-
if (state.agents.size > 0) return "working";
|
|
31076
|
-
if (state.monitors.size > 0) return "monitoring";
|
|
31077
|
-
return null;
|
|
31078
|
-
}
|
|
31079
|
-
};
|
|
31080
|
-
}
|
|
31081
|
-
const layer$64 = Layer.effect(ThreadBackgroundLivenessService, Effect.sync(make$75));
|
|
31082
|
-
//#endregion
|
|
31083
31512
|
//#region src/persistence/Services/ProjectionCheckpoints.ts
|
|
31084
31513
|
/**
|
|
31085
31514
|
* ProjectionCheckpointRepository - Projection repository interface for checkpoints.
|
|
@@ -31647,12 +32076,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
|
|
|
31647
32076
|
stderrInvalidUtf8: stderr.invalidUtf8
|
|
31648
32077
|
};
|
|
31649
32078
|
});
|
|
31650
|
-
const make$
|
|
32079
|
+
const make$75 = Effect.fn("ProcessRunner.make")(function* () {
|
|
31651
32080
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
31652
32081
|
const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
|
|
31653
32082
|
return ProcessRunner.of({ run });
|
|
31654
32083
|
});
|
|
31655
|
-
const layer$63 = Layer.effect(ProcessRunner, make$
|
|
32084
|
+
const layer$63 = Layer.effect(ProcessRunner, make$75());
|
|
31656
32085
|
//#endregion
|
|
31657
32086
|
//#region src/project/RepositoryIdentityResolver.ts
|
|
31658
32087
|
const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
|
|
@@ -31743,7 +32172,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
|
|
|
31743
32172
|
rootPath: cacheKey
|
|
31744
32173
|
}) : null;
|
|
31745
32174
|
});
|
|
31746
|
-
const make$
|
|
32175
|
+
const make$74 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
|
|
31747
32176
|
const processRunner = yield* ProcessRunner;
|
|
31748
32177
|
const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
|
|
31749
32178
|
capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
|
|
@@ -31758,7 +32187,7 @@ const make$73 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
|
|
|
31758
32187
|
});
|
|
31759
32188
|
return RepositoryIdentityResolver.of({ resolve });
|
|
31760
32189
|
});
|
|
31761
|
-
const layer$62 = Layer.effect(RepositoryIdentityResolver, make$
|
|
32190
|
+
const layer$62 = Layer.effect(RepositoryIdentityResolver, make$74()).pipe(Layer.provide(layer$63));
|
|
31762
32191
|
//#endregion
|
|
31763
32192
|
//#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
|
|
31764
32193
|
const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
|
|
@@ -32114,6 +32543,10 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32114
32543
|
archived_at AS "archivedAt",
|
|
32115
32544
|
settled_override AS "settledOverride",
|
|
32116
32545
|
settled_at AS "settledAt",
|
|
32546
|
+
lifecycle AS "lifecycle",
|
|
32547
|
+
lifecycle_reason AS "lifecycleReason",
|
|
32548
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32549
|
+
last_engaged_at AS "lastEngagedAt",
|
|
32117
32550
|
snoozed_until AS "snoozedUntil",
|
|
32118
32551
|
snoozed_at AS "snoozedAt",
|
|
32119
32552
|
pinned_at AS "pinnedAt",
|
|
@@ -32151,6 +32584,10 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32151
32584
|
archived_at AS "archivedAt",
|
|
32152
32585
|
settled_override AS "settledOverride",
|
|
32153
32586
|
settled_at AS "settledAt",
|
|
32587
|
+
lifecycle AS "lifecycle",
|
|
32588
|
+
lifecycle_reason AS "lifecycleReason",
|
|
32589
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32590
|
+
last_engaged_at AS "lastEngagedAt",
|
|
32154
32591
|
snoozed_until AS "snoozedUntil",
|
|
32155
32592
|
snoozed_at AS "snoozedAt",
|
|
32156
32593
|
pinned_at AS "pinnedAt",
|
|
@@ -32190,6 +32627,10 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32190
32627
|
archived_at AS "archivedAt",
|
|
32191
32628
|
settled_override AS "settledOverride",
|
|
32192
32629
|
settled_at AS "settledAt",
|
|
32630
|
+
lifecycle AS "lifecycle",
|
|
32631
|
+
lifecycle_reason AS "lifecycleReason",
|
|
32632
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
32633
|
+
last_engaged_at AS "lastEngagedAt",
|
|
32193
32634
|
snoozed_until AS "snoozedUntil",
|
|
32194
32635
|
snoozed_at AS "snoozedAt",
|
|
32195
32636
|
pinned_at AS "pinnedAt",
|
|
@@ -32654,6 +33095,10 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
32654
33095
|
archived_at AS "archivedAt",
|
|
32655
33096
|
settled_override AS "settledOverride",
|
|
32656
33097
|
settled_at AS "settledAt",
|
|
33098
|
+
lifecycle AS "lifecycle",
|
|
33099
|
+
lifecycle_reason AS "lifecycleReason",
|
|
33100
|
+
lifecycle_changed_at AS "lifecycleChangedAt",
|
|
33101
|
+
last_engaged_at AS "lastEngagedAt",
|
|
32657
33102
|
snoozed_until AS "snoozedUntil",
|
|
32658
33103
|
snoozed_at AS "snoozedAt",
|
|
32659
33104
|
pinned_at AS "pinnedAt",
|
|
@@ -33346,6 +33791,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33346
33791
|
archivedAt: row.archivedAt,
|
|
33347
33792
|
settledOverride: row.settledOverride,
|
|
33348
33793
|
settledAt: row.settledAt,
|
|
33794
|
+
lifecycle: row.lifecycle,
|
|
33795
|
+
lifecycleReason: row.lifecycleReason,
|
|
33796
|
+
lifecycleChangedAt: row.lifecycleChangedAt,
|
|
33797
|
+
lastEngagedAt: row.lastEngagedAt,
|
|
33798
|
+
doneAt: row.settledAt,
|
|
33349
33799
|
snoozedUntil: row.snoozedUntil,
|
|
33350
33800
|
snoozedAt: row.snoozedAt,
|
|
33351
33801
|
pinnedAt: row.pinnedAt,
|
|
@@ -33489,6 +33939,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33489
33939
|
archivedAt: row.archivedAt,
|
|
33490
33940
|
settledOverride: row.settledOverride,
|
|
33491
33941
|
settledAt: row.settledAt,
|
|
33942
|
+
lifecycle: row.lifecycle,
|
|
33943
|
+
lifecycleReason: row.lifecycleReason,
|
|
33944
|
+
lifecycleChangedAt: row.lifecycleChangedAt,
|
|
33945
|
+
lastEngagedAt: row.lastEngagedAt,
|
|
33946
|
+
doneAt: row.settledAt,
|
|
33492
33947
|
snoozedUntil: row.snoozedUntil,
|
|
33493
33948
|
snoozedAt: row.snoozedAt,
|
|
33494
33949
|
pinnedAt: row.pinnedAt,
|
|
@@ -33555,6 +34010,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33555
34010
|
archivedAt: row.archivedAt,
|
|
33556
34011
|
settledOverride: row.settledOverride,
|
|
33557
34012
|
settledAt: row.settledAt,
|
|
34013
|
+
lifecycle: row.lifecycle,
|
|
34014
|
+
lifecycleReason: row.lifecycleReason,
|
|
34015
|
+
lifecycleChangedAt: row.lifecycleChangedAt,
|
|
34016
|
+
lastEngagedAt: row.lastEngagedAt,
|
|
34017
|
+
doneAt: row.settledAt,
|
|
33558
34018
|
snoozedUntil: row.snoozedUntil,
|
|
33559
34019
|
snoozedAt: row.snoozedAt,
|
|
33560
34020
|
pinnedAt: row.pinnedAt,
|
|
@@ -33621,6 +34081,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33621
34081
|
archivedAt: row.archivedAt,
|
|
33622
34082
|
settledOverride: row.settledOverride,
|
|
33623
34083
|
settledAt: row.settledAt,
|
|
34084
|
+
lifecycle: row.lifecycle,
|
|
34085
|
+
lifecycleReason: row.lifecycleReason,
|
|
34086
|
+
lifecycleChangedAt: row.lifecycleChangedAt,
|
|
34087
|
+
lastEngagedAt: row.lastEngagedAt,
|
|
34088
|
+
doneAt: row.settledAt,
|
|
33624
34089
|
snoozedUntil: row.snoozedUntil,
|
|
33625
34090
|
snoozedAt: row.snoozedAt,
|
|
33626
34091
|
pinnedAt: row.pinnedAt,
|
|
@@ -33735,6 +34200,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33735
34200
|
archivedAt: threadRow.value.archivedAt,
|
|
33736
34201
|
settledOverride: threadRow.value.settledOverride,
|
|
33737
34202
|
settledAt: threadRow.value.settledAt,
|
|
34203
|
+
lifecycle: threadRow.value.lifecycle,
|
|
34204
|
+
lifecycleReason: threadRow.value.lifecycleReason,
|
|
34205
|
+
lifecycleChangedAt: threadRow.value.lifecycleChangedAt,
|
|
34206
|
+
lastEngagedAt: threadRow.value.lastEngagedAt,
|
|
34207
|
+
doneAt: threadRow.value.settledAt,
|
|
33738
34208
|
snoozedUntil: threadRow.value.snoozedUntil,
|
|
33739
34209
|
snoozedAt: threadRow.value.snoozedAt,
|
|
33740
34210
|
pinnedAt: threadRow.value.pinnedAt,
|
|
@@ -33802,6 +34272,11 @@ const makeProjectionSnapshotQuery = Effect.gen(function* () {
|
|
|
33802
34272
|
archivedAt: threadRow.value.archivedAt,
|
|
33803
34273
|
settledOverride: threadRow.value.settledOverride,
|
|
33804
34274
|
settledAt: threadRow.value.settledAt,
|
|
34275
|
+
lifecycle: threadRow.value.lifecycle,
|
|
34276
|
+
lifecycleReason: threadRow.value.lifecycleReason,
|
|
34277
|
+
lifecycleChangedAt: threadRow.value.lifecycleChangedAt,
|
|
34278
|
+
lastEngagedAt: threadRow.value.lastEngagedAt,
|
|
34279
|
+
doneAt: threadRow.value.settledAt,
|
|
33805
34280
|
snoozedUntil: threadRow.value.snoozedUntil,
|
|
33806
34281
|
snoozedAt: threadRow.value.snoozedAt,
|
|
33807
34282
|
pinnedAt: threadRow.value.pinnedAt,
|
|
@@ -33927,9 +34402,185 @@ const OrchestrationProjectionSnapshotQueryLive = Layer.effect(ProjectionSnapshot
|
|
|
33927
34402
|
//#region src/orchestration/Services/ThreadEventStream.ts
|
|
33928
34403
|
var ThreadEventStreamService = class extends Context.Service()("@p4code/cli/orchestration/Services/ThreadEventStream/ThreadEventStreamService") {};
|
|
33929
34404
|
//#endregion
|
|
34405
|
+
//#region src/orchestration/ThreadReviewProjection.ts
|
|
34406
|
+
const isMessagePayload = Schema$1.is(ThreadMessageSentPayload);
|
|
34407
|
+
const MAX_MESSAGE_IDENTITY_LENGTH = 1024;
|
|
34408
|
+
const MAX_PREVIEW_DEPTH = 12;
|
|
34409
|
+
const MAX_PREVIEW_NODES = 512;
|
|
34410
|
+
const TRUNCATION_MARKER$1 = "\n[truncated; recover source events]\n";
|
|
34411
|
+
function excerpt(text, length) {
|
|
34412
|
+
if (text.length <= length) return text;
|
|
34413
|
+
const sideLength = Math.max(0, Math.floor((length - 36) / 2));
|
|
34414
|
+
return text.slice(0, sideLength).replace(/[\uD800-\uDBFF]$/, "") + TRUNCATION_MARKER$1 + (sideLength > 0 ? text.slice(-sideLength).replace(/^[\uDC00-\uDFFF]/, "") : "");
|
|
34415
|
+
}
|
|
34416
|
+
/** Serialize only a bounded prefix, without walking or copying an oversized tool result. */
|
|
34417
|
+
function payloadPreview(payload) {
|
|
34418
|
+
let remainingNodes = MAX_PREVIEW_NODES;
|
|
34419
|
+
function* parts(value, depth) {
|
|
34420
|
+
if (--remainingNodes < 0 || depth > MAX_PREVIEW_DEPTH) {
|
|
34421
|
+
yield TRUNCATION_MARKER$1;
|
|
34422
|
+
return;
|
|
34423
|
+
}
|
|
34424
|
+
if (typeof value === "string") yield JSON.stringify(excerpt(value, THREAD_REVIEW_ITEM_MAX_BYTES));
|
|
34425
|
+
else if (value === null || typeof value !== "object") yield JSON.stringify(value) ?? "null";
|
|
34426
|
+
else {
|
|
34427
|
+
const array = Array.isArray(value);
|
|
34428
|
+
yield array ? "[" : "{";
|
|
34429
|
+
let first = true;
|
|
34430
|
+
for (const key in value) {
|
|
34431
|
+
if (!Object.hasOwn(value, key)) continue;
|
|
34432
|
+
if (remainingNodes <= 0) {
|
|
34433
|
+
yield TRUNCATION_MARKER$1;
|
|
34434
|
+
break;
|
|
34435
|
+
}
|
|
34436
|
+
if (!first) yield ",";
|
|
34437
|
+
first = false;
|
|
34438
|
+
if (!array) yield JSON.stringify(excerpt(key, THREAD_REVIEW_ITEM_MAX_BYTES)) + ":";
|
|
34439
|
+
yield* parts(value[key], depth + 1);
|
|
34440
|
+
}
|
|
34441
|
+
yield array ? "]" : "}";
|
|
34442
|
+
}
|
|
34443
|
+
}
|
|
34444
|
+
let text = "";
|
|
34445
|
+
let truncated = false;
|
|
34446
|
+
for (const part of parts(payload, 0)) {
|
|
34447
|
+
if (part.includes(TRUNCATION_MARKER$1) || part.includes(JSON.stringify(TRUNCATION_MARKER$1).slice(1, -1))) truncated = true;
|
|
34448
|
+
const remaining = THREAD_REVIEW_ITEM_MAX_BYTES - text.length;
|
|
34449
|
+
if (part.length > remaining) {
|
|
34450
|
+
text += part.slice(0, remaining);
|
|
34451
|
+
truncated = true;
|
|
34452
|
+
break;
|
|
34453
|
+
}
|
|
34454
|
+
text += part;
|
|
34455
|
+
}
|
|
34456
|
+
return {
|
|
34457
|
+
text,
|
|
34458
|
+
truncated
|
|
34459
|
+
};
|
|
34460
|
+
}
|
|
34461
|
+
function fitItem(item) {
|
|
34462
|
+
let result = item;
|
|
34463
|
+
let bytes = Buffer.byteLength(JSON.stringify(result));
|
|
34464
|
+
while (bytes > THREAD_REVIEW_ITEM_MAX_BYTES) {
|
|
34465
|
+
const text = result.kind === "message" ? result.text : result.payload;
|
|
34466
|
+
const length = Math.max(36, Math.floor(text.length / 2));
|
|
34467
|
+
result = result.kind === "message" ? {
|
|
34468
|
+
...result,
|
|
34469
|
+
text: excerpt(text, length),
|
|
34470
|
+
truncated: true
|
|
34471
|
+
} : {
|
|
34472
|
+
...result,
|
|
34473
|
+
payload: excerpt(text, length),
|
|
34474
|
+
truncated: true
|
|
34475
|
+
};
|
|
34476
|
+
bytes = Buffer.byteLength(JSON.stringify(result));
|
|
34477
|
+
}
|
|
34478
|
+
return result;
|
|
34479
|
+
}
|
|
34480
|
+
/** Page-local folds follow the projector: streaming appends; nonempty completion replaces. */
|
|
34481
|
+
function createThreadReviewPage(input) {
|
|
34482
|
+
const items = [];
|
|
34483
|
+
const messageIndexes = /* @__PURE__ */ new Map();
|
|
34484
|
+
let nextAfterSequence = input.afterSequence;
|
|
34485
|
+
let scannedEvents = 0;
|
|
34486
|
+
let itemBytes = 0;
|
|
34487
|
+
const envelopeBytes = Buffer.byteLength(JSON.stringify({
|
|
34488
|
+
threadId: input.threadId,
|
|
34489
|
+
items: [],
|
|
34490
|
+
throughSequence: input.throughSequence,
|
|
34491
|
+
nextAfterSequence: Number.MAX_SAFE_INTEGER,
|
|
34492
|
+
hasMore: false,
|
|
34493
|
+
scannedEvents: Number.MAX_SAFE_INTEGER
|
|
34494
|
+
}));
|
|
34495
|
+
function offer(event, sourceTruncated = false) {
|
|
34496
|
+
if (event.sequence > input.throughSequence) return false;
|
|
34497
|
+
if (event.aggregateKind !== "thread" || event.aggregateId !== input.threadId) {
|
|
34498
|
+
nextAfterSequence = event.sequence;
|
|
34499
|
+
scannedEvents += 1;
|
|
34500
|
+
return true;
|
|
34501
|
+
}
|
|
34502
|
+
let item;
|
|
34503
|
+
let index;
|
|
34504
|
+
let messageKey;
|
|
34505
|
+
if (event.type === "thread.message-sent" && !sourceTruncated && isMessagePayload(event.payload) && event.payload.role === "assistant" && !event.payload.attachments?.length && event.payload.messageId.length + (event.payload.turnId?.length ?? 0) <= MAX_MESSAGE_IDENTITY_LENGTH) {
|
|
34506
|
+
const payload = event.payload;
|
|
34507
|
+
messageKey = JSON.stringify([payload.turnId, payload.messageId]);
|
|
34508
|
+
index = messageIndexes.get(messageKey);
|
|
34509
|
+
const previous = index === void 0 ? void 0 : items[index];
|
|
34510
|
+
const previousMessage = previous?.kind === "message" ? previous : void 0;
|
|
34511
|
+
const replaces = !payload.streaming && payload.text.length > 0;
|
|
34512
|
+
const part = excerpt(payload.text, THREAD_REVIEW_ITEM_MAX_BYTES);
|
|
34513
|
+
item = fitItem({
|
|
34514
|
+
kind: "message",
|
|
34515
|
+
firstSequence: previousMessage?.firstSequence ?? event.sequence,
|
|
34516
|
+
lastSequence: event.sequence,
|
|
34517
|
+
messageId: payload.messageId,
|
|
34518
|
+
turnId: payload.turnId,
|
|
34519
|
+
role: payload.role,
|
|
34520
|
+
operation: replaces ? "replace" : previousMessage?.operation ?? "append",
|
|
34521
|
+
complete: !payload.streaming,
|
|
34522
|
+
text: replaces ? part : (previousMessage?.text ?? "") + part,
|
|
34523
|
+
truncated: part !== payload.text || !replaces && (previousMessage?.truncated ?? false)
|
|
34524
|
+
});
|
|
34525
|
+
} else {
|
|
34526
|
+
const preview = sourceTruncated && typeof event.payload === "string" ? {
|
|
34527
|
+
text: event.payload,
|
|
34528
|
+
truncated: true
|
|
34529
|
+
} : payloadPreview(event.payload);
|
|
34530
|
+
item = fitItem({
|
|
34531
|
+
kind: "event",
|
|
34532
|
+
type: event.type,
|
|
34533
|
+
firstSequence: event.sequence,
|
|
34534
|
+
lastSequence: event.sequence,
|
|
34535
|
+
payload: preview.text,
|
|
34536
|
+
truncated: preview.truncated
|
|
34537
|
+
});
|
|
34538
|
+
}
|
|
34539
|
+
const previousBytes = index === void 0 ? 0 : Buffer.byteLength(JSON.stringify(items[index]));
|
|
34540
|
+
const nextBytes = itemBytes - previousBytes + Buffer.byteLength(JSON.stringify(item));
|
|
34541
|
+
if (index === void 0 && items.length >= 100 || envelopeBytes + nextBytes + items.length + 1 > 48e3) return false;
|
|
34542
|
+
if (index === void 0) {
|
|
34543
|
+
if (messageKey !== void 0) messageIndexes.set(messageKey, items.length);
|
|
34544
|
+
items.push(item);
|
|
34545
|
+
} else items[index] = item;
|
|
34546
|
+
itemBytes = nextBytes;
|
|
34547
|
+
nextAfterSequence = event.sequence;
|
|
34548
|
+
scannedEvents += 1;
|
|
34549
|
+
return true;
|
|
34550
|
+
}
|
|
34551
|
+
return {
|
|
34552
|
+
offer,
|
|
34553
|
+
offerStored(row) {
|
|
34554
|
+
if (row.payloadJson.length <= 8e3) try {
|
|
34555
|
+
return offer({
|
|
34556
|
+
...row,
|
|
34557
|
+
payload: JSON.parse(row.payloadJson)
|
|
34558
|
+
});
|
|
34559
|
+
} catch {}
|
|
34560
|
+
return offer({
|
|
34561
|
+
...row,
|
|
34562
|
+
payload: row.payloadJson.slice(0, THREAD_REVIEW_ITEM_MAX_BYTES)
|
|
34563
|
+
}, true);
|
|
34564
|
+
},
|
|
34565
|
+
finish(exhausted) {
|
|
34566
|
+
if (exhausted) nextAfterSequence = Math.max(nextAfterSequence, input.throughSequence);
|
|
34567
|
+
return {
|
|
34568
|
+
threadId: input.threadId,
|
|
34569
|
+
items: items.toSorted((a, b) => a.lastSequence - b.lastSequence),
|
|
34570
|
+
throughSequence: input.throughSequence,
|
|
34571
|
+
nextAfterSequence,
|
|
34572
|
+
hasMore: nextAfterSequence < input.throughSequence,
|
|
34573
|
+
scannedEvents
|
|
34574
|
+
};
|
|
34575
|
+
}
|
|
34576
|
+
};
|
|
34577
|
+
}
|
|
34578
|
+
//#endregion
|
|
33930
34579
|
//#region src/orchestration/Layers/ThreadEventStream.ts
|
|
34580
|
+
const REVIEW_SOURCE_PAGE_SIZE = 100;
|
|
33931
34581
|
const makeThreadEventStream = Effect.gen(function* () {
|
|
33932
34582
|
const engine = yield* OrchestrationEngineService;
|
|
34583
|
+
const eventStore = yield* OrchestrationEventStore;
|
|
33933
34584
|
const isThreadEvent = (threadId) => (event) => event.aggregateKind === "thread" && event.aggregateId === threadId;
|
|
33934
34585
|
const watch = (input) => Stream.unwrap(Effect.gen(function* () {
|
|
33935
34586
|
const matchesThread = isThreadEvent(input.threadId);
|
|
@@ -33971,9 +34622,38 @@ const makeThreadEventStream = Effect.gen(function* () {
|
|
|
33971
34622
|
hasMore
|
|
33972
34623
|
};
|
|
33973
34624
|
});
|
|
34625
|
+
const readReview = Effect.fn("ThreadEventStream.readReview")(function* (input) {
|
|
34626
|
+
const headSequence = yield* engine.latestSequence;
|
|
34627
|
+
const throughSequence = Math.min(input.throughSequence ?? headSequence, headSequence);
|
|
34628
|
+
const afterSequence = input.afterSequence ?? 0;
|
|
34629
|
+
const page = createThreadReviewPage({
|
|
34630
|
+
threadId: input.threadId,
|
|
34631
|
+
afterSequence,
|
|
34632
|
+
throughSequence
|
|
34633
|
+
});
|
|
34634
|
+
if (afterSequence >= throughSequence) return page.finish(true);
|
|
34635
|
+
let cursor = afterSequence;
|
|
34636
|
+
let scanned = 0;
|
|
34637
|
+
while (scanned < 2e3 && cursor < throughSequence) {
|
|
34638
|
+
const limit = Math.min(REVIEW_SOURCE_PAGE_SIZE, THREAD_REVIEW_SCAN_LIMIT - scanned);
|
|
34639
|
+
const rows = yield* eventStore.readReviewPage({
|
|
34640
|
+
afterSequence: cursor,
|
|
34641
|
+
throughSequence,
|
|
34642
|
+
limit
|
|
34643
|
+
});
|
|
34644
|
+
for (const row of rows) {
|
|
34645
|
+
if (!page.offerStored(row)) return page.finish(false);
|
|
34646
|
+
cursor = row.sequence;
|
|
34647
|
+
scanned += 1;
|
|
34648
|
+
}
|
|
34649
|
+
if (rows.length < limit) return page.finish(true);
|
|
34650
|
+
}
|
|
34651
|
+
return page.finish(false);
|
|
34652
|
+
});
|
|
33974
34653
|
return ThreadEventStreamService.of({
|
|
33975
34654
|
watch,
|
|
33976
|
-
read
|
|
34655
|
+
read,
|
|
34656
|
+
readReview
|
|
33977
34657
|
});
|
|
33978
34658
|
});
|
|
33979
34659
|
const ThreadEventStreamLive = Layer.effect(ThreadEventStreamService, makeThreadEventStream);
|
|
@@ -33990,7 +34670,7 @@ const OrchestrationProjectionPipelineLayerLive = OrchestrationProjectionPipeline
|
|
|
33990
34670
|
const ThreadBackgroundLivenessLayerLive = layer$64;
|
|
33991
34671
|
const OrchestrationInfrastructureLayerLive = Layer.mergeAll(OrchestrationProjectionSnapshotQueryLive, OrchestrationEventInfrastructureLayerLive, OrchestrationProjectionPipelineLayerLive, ThreadBackgroundLivenessLayerLive);
|
|
33992
34672
|
const OrchestrationEngineLayerLive = OrchestrationEngineLive.pipe(Layer.provide(OrchestrationInfrastructureLayerLive));
|
|
33993
|
-
const OrchestrationLayerLive = Layer.mergeAll(OrchestrationInfrastructureLayerLive, OrchestrationEngineLayerLive, ThreadEventStreamLive.pipe(Layer.provide(OrchestrationEngineLayerLive)));
|
|
34673
|
+
const OrchestrationLayerLive = Layer.mergeAll(OrchestrationInfrastructureLayerLive, OrchestrationEngineLayerLive, ThreadEventStreamLive.pipe(Layer.provide(OrchestrationEngineLayerLive), Layer.provide(OrchestrationEventStoreLive)));
|
|
33994
34674
|
//#endregion
|
|
33995
34675
|
//#region ../../packages/shared/src/keybindings.ts
|
|
33996
34676
|
const DEFAULT_KEYBINDINGS = [
|
|
@@ -34462,7 +35142,7 @@ function mergeWithDefaultKeybindings(custom) {
|
|
|
34462
35142
|
* Keybindings - Service tag for keybinding configuration operations.
|
|
34463
35143
|
*/
|
|
34464
35144
|
var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
|
|
34465
|
-
const make$
|
|
35145
|
+
const make$73 = Effect.gen(function* () {
|
|
34466
35146
|
const { keybindingsConfigPath } = yield* ServerConfig$1;
|
|
34467
35147
|
const fs = yield* FileSystem.FileSystem;
|
|
34468
35148
|
const path = yield* Path.Path;
|
|
@@ -34723,7 +35403,7 @@ const make$72 = Effect.gen(function* () {
|
|
|
34723
35403
|
}))
|
|
34724
35404
|
};
|
|
34725
35405
|
});
|
|
34726
|
-
const layer$61 = Layer.effect(Keybindings, make$
|
|
35406
|
+
const layer$61 = Layer.effect(Keybindings, make$73);
|
|
34727
35407
|
//#endregion
|
|
34728
35408
|
//#region src/process/externalLauncher.ts
|
|
34729
35409
|
/**
|
|
@@ -34950,7 +35630,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
|
|
|
34950
35630
|
cause
|
|
34951
35631
|
}));
|
|
34952
35632
|
});
|
|
34953
|
-
const make$
|
|
35633
|
+
const make$72 = Effect.gen(function* () {
|
|
34954
35634
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
34955
35635
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
34956
35636
|
const path = yield* Path.Path;
|
|
@@ -34961,7 +35641,7 @@ const make$71 = Effect.gen(function* () {
|
|
|
34961
35641
|
launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
|
|
34962
35642
|
});
|
|
34963
35643
|
});
|
|
34964
|
-
const layer$60 = Layer.effect(ExternalLauncher, make$
|
|
35644
|
+
const layer$60 = Layer.effect(ExternalLauncher, make$72);
|
|
34965
35645
|
//#endregion
|
|
34966
35646
|
//#region src/orchestration/Services/OrchestrationReactor.ts
|
|
34967
35647
|
/**
|
|
@@ -34979,7 +35659,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
|
|
|
34979
35659
|
//#endregion
|
|
34980
35660
|
//#region src/serverLifecycleEvents.ts
|
|
34981
35661
|
var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
|
|
34982
|
-
const make$
|
|
35662
|
+
const make$71 = Effect.gen(function* () {
|
|
34983
35663
|
const pubsub = yield* PubSub.unbounded();
|
|
34984
35664
|
const state = yield* Ref.make({
|
|
34985
35665
|
sequence: 0,
|
|
@@ -35003,7 +35683,7 @@ const make$70 = Effect.gen(function* () {
|
|
|
35003
35683
|
}
|
|
35004
35684
|
};
|
|
35005
35685
|
});
|
|
35006
|
-
const layer$59 = Layer.effect(ServerLifecycleEvents, make$
|
|
35686
|
+
const layer$59 = Layer.effect(ServerLifecycleEvents, make$71);
|
|
35007
35687
|
//#endregion
|
|
35008
35688
|
//#region src/telemetry/Identify.ts
|
|
35009
35689
|
const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
|
|
@@ -35176,7 +35856,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
|
|
|
35176
35856
|
/** No-op layer for callers that intentionally disable telemetry. */
|
|
35177
35857
|
static layerTest = Layer.succeed(AnalyticsService, inert);
|
|
35178
35858
|
};
|
|
35179
|
-
const make$
|
|
35859
|
+
const make$70 = Effect.gen(function* () {
|
|
35180
35860
|
const telemetryConfig = yield* TelemetryEnvConfig;
|
|
35181
35861
|
const posthogKey = telemetryConfig.posthogKey.trim();
|
|
35182
35862
|
if (!telemetryConfig.enabled || posthogKey === "") return inert;
|
|
@@ -35246,7 +35926,7 @@ const make$69 = Effect.gen(function* () {
|
|
|
35246
35926
|
flush
|
|
35247
35927
|
});
|
|
35248
35928
|
});
|
|
35249
|
-
const layer$58 = Layer.effect(AnalyticsService, make$
|
|
35929
|
+
const layer$58 = Layer.effect(AnalyticsService, make$70);
|
|
35250
35930
|
AnalyticsService.layerTest;
|
|
35251
35931
|
//#endregion
|
|
35252
35932
|
//#region src/service/pinnedRuntime.ts
|
|
@@ -35593,7 +36273,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
|
|
|
35593
36273
|
}
|
|
35594
36274
|
};
|
|
35595
36275
|
var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
|
|
35596
|
-
const make$
|
|
36276
|
+
const make$69 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
35597
36277
|
const hostExecPath = yield* HostProcessExecutablePath;
|
|
35598
36278
|
const hostArguments = yield* HostProcessArguments;
|
|
35599
36279
|
const host = input.host ?? {
|
|
@@ -35815,7 +36495,7 @@ const make$68 = Effect.fn("cloud.boot_service.make")(function* (input) {
|
|
|
35815
36495
|
logPath
|
|
35816
36496
|
});
|
|
35817
36497
|
});
|
|
35818
|
-
const layer$57 = (input) => Layer.effect(BootService, make$
|
|
36498
|
+
const layer$57 = (input) => Layer.effect(BootService, make$69(input));
|
|
35819
36499
|
//#endregion
|
|
35820
36500
|
//#region src/service/selfUpdate.ts
|
|
35821
36501
|
/**
|
|
@@ -35890,7 +36570,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
|
|
|
35890
36570
|
return null;
|
|
35891
36571
|
});
|
|
35892
36572
|
var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
|
|
35893
|
-
const make$
|
|
36573
|
+
const make$68 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
35894
36574
|
const serverConfig = yield* ServerConfig$1;
|
|
35895
36575
|
const fs = yield* FileSystem.FileSystem;
|
|
35896
36576
|
const path = yield* Path.Path;
|
|
@@ -36040,7 +36720,7 @@ const make$67 = Effect.fn("cloud.server_self_update.make")(function* (options) {
|
|
|
36040
36720
|
});
|
|
36041
36721
|
return ServerSelfUpdate.of({ update });
|
|
36042
36722
|
});
|
|
36043
|
-
const layer$56 = Layer.effect(ServerSelfUpdate, make$
|
|
36723
|
+
const layer$56 = Layer.effect(ServerSelfUpdate, make$68()).pipe(Layer.provide(layer$63));
|
|
36044
36724
|
//#endregion
|
|
36045
36725
|
//#region src/environment/ServerEnvironmentLabel.ts
|
|
36046
36726
|
const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
|
|
@@ -36172,7 +36852,7 @@ function platformArch(architecture) {
|
|
|
36172
36852
|
default: return "other";
|
|
36173
36853
|
}
|
|
36174
36854
|
}
|
|
36175
|
-
const make$
|
|
36855
|
+
const make$67 = Effect.gen(function* () {
|
|
36176
36856
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
36177
36857
|
const path = yield* Path.Path;
|
|
36178
36858
|
const serverConfig = yield* ServerConfig$1;
|
|
@@ -36221,6 +36901,7 @@ const make$66 = Effect.gen(function* () {
|
|
|
36221
36901
|
connectionProbe: true,
|
|
36222
36902
|
pullRequests: true,
|
|
36223
36903
|
threadSettlement: true,
|
|
36904
|
+
threadLifecycleV2: true,
|
|
36224
36905
|
threadSnooze: true,
|
|
36225
36906
|
threadPinning: true,
|
|
36226
36907
|
threadFork: true,
|
|
@@ -36239,7 +36920,7 @@ const make$66 = Effect.gen(function* () {
|
|
|
36239
36920
|
* state. It intentionally has no fallback Layer.succeed value: callers must
|
|
36240
36921
|
* provide the external platform services and a ServerConfig.
|
|
36241
36922
|
*/
|
|
36242
|
-
const layer$55 = Layer.effect(ServerEnvironment, make$
|
|
36923
|
+
const layer$55 = Layer.effect(ServerEnvironment, make$67).pipe(Layer.provide(layer$63));
|
|
36243
36924
|
//#endregion
|
|
36244
36925
|
//#region src/provider/Services/ProviderSessionReaper.ts
|
|
36245
36926
|
var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
|
|
@@ -36381,7 +37062,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
|
|
|
36381
37062
|
yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
|
|
36382
37063
|
});
|
|
36383
37064
|
const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
|
|
36384
|
-
const make$
|
|
37065
|
+
const make$66 = Effect.gen(function* () {
|
|
36385
37066
|
const serverConfig = yield* ServerConfig$1;
|
|
36386
37067
|
const keybindings = yield* Keybindings;
|
|
36387
37068
|
const orchestrationReactor = yield* OrchestrationReactor;
|
|
@@ -36522,7 +37203,7 @@ const make$65 = Effect.gen(function* () {
|
|
|
36522
37203
|
enqueueCommand: commandGate.enqueueCommand
|
|
36523
37204
|
};
|
|
36524
37205
|
});
|
|
36525
|
-
const layer$54 = Layer.effect(ServerRuntimeStartup, make$
|
|
37206
|
+
const layer$54 = Layer.effect(ServerRuntimeStartup, make$66);
|
|
36526
37207
|
//#endregion
|
|
36527
37208
|
//#region src/serverRuntimeState.ts
|
|
36528
37209
|
const PersistedServerRuntimeState = Schema$1.Struct({
|
|
@@ -36679,7 +37360,7 @@ function expandHomePath$2(input, path) {
|
|
|
36679
37360
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
36680
37361
|
return input;
|
|
36681
37362
|
}
|
|
36682
|
-
const make$
|
|
37363
|
+
const make$65 = Effect.gen(function* () {
|
|
36683
37364
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
36684
37365
|
const path = yield* Path.Path;
|
|
36685
37366
|
const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
|
|
@@ -36736,7 +37417,7 @@ const make$64 = Effect.gen(function* () {
|
|
|
36736
37417
|
resolveRelativePathWithinRoot
|
|
36737
37418
|
});
|
|
36738
37419
|
});
|
|
36739
|
-
const layer$53 = Layer.effect(WorkspacePaths, make$
|
|
37420
|
+
const layer$53 = Layer.effect(WorkspacePaths, make$65);
|
|
36740
37421
|
//#endregion
|
|
36741
37422
|
//#region src/cli/project.ts
|
|
36742
37423
|
const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
|
|
@@ -36871,7 +37552,7 @@ const findActiveProjectTarget = Effect.fn("findActiveProjectTarget")(function* (
|
|
|
36871
37552
|
operation: "resolveProjectTarget",
|
|
36872
37553
|
identifier: input.identifier
|
|
36873
37554
|
});
|
|
36874
|
-
const activeProjects = input.snapshot.projects.filter((project) => project.deletedAt
|
|
37555
|
+
const activeProjects = input.snapshot.projects.filter((project) => project.deletedAt == null);
|
|
36875
37556
|
const exactIdMatch = activeProjects.find((project) => project.id === trimmedIdentifier);
|
|
36876
37557
|
if (exactIdMatch) return {
|
|
36877
37558
|
id: exactIdMatch.id,
|
|
@@ -36895,7 +37576,7 @@ const findActiveProjectTarget = Effect.fn("findActiveProjectTarget")(function* (
|
|
|
36895
37576
|
};
|
|
36896
37577
|
});
|
|
36897
37578
|
const fetchLiveOrchestrationSnapshot = (origin, bearerToken) => Effect.gen(function* () {
|
|
36898
|
-
return yield* (yield* makeLiveServerClient(origin)).orchestration.
|
|
37579
|
+
return yield* (yield* makeLiveServerClient(origin)).orchestration.shellSnapshot({ headers: { authorization: `Bearer ${bearerToken}` } });
|
|
36899
37580
|
}).pipe(withProjectCliLiveServerTimeout, Effect.mapError(projectCommandErrorFromLiveServerRequest));
|
|
36900
37581
|
const dispatchLiveOrchestrationCommand = (origin, bearerToken, command) => Effect.gen(function* () {
|
|
36901
37582
|
yield* (yield* makeLiveServerClient(origin)).orchestration.dispatch({
|
|
@@ -36904,7 +37585,7 @@ const dispatchLiveOrchestrationCommand = (origin, bearerToken, command) => Effec
|
|
|
36904
37585
|
});
|
|
36905
37586
|
}).pipe(withProjectCliLiveServerTimeout, Effect.mapError(projectCommandErrorFromLiveServerRequest));
|
|
36906
37587
|
const getOfflineSnapshot = Effect.fn("getOfflineSnapshot")(function* () {
|
|
36907
|
-
return yield* (yield* ProjectionSnapshotQuery).
|
|
37588
|
+
return yield* (yield* ProjectionSnapshotQuery).getCommandReadModel();
|
|
36908
37589
|
});
|
|
36909
37590
|
const tryResolveLiveProjectExecutionMode = Effect.fn("tryResolveLiveProjectExecutionMode")(function* (environmentAuth, config) {
|
|
36910
37591
|
const runtimeState = yield* readPersistedServerRuntimeState(config.serverRuntimeStatePath);
|
|
@@ -36952,7 +37633,7 @@ const projectAddCommand = Command.make("add", {
|
|
|
36952
37633
|
title: Flag.string("title").pipe(Flag.withDescription("Optional project title."), Flag.optional)
|
|
36953
37634
|
}).pipe(Command.withDescription("Add a project."), Command.withHandler((flags) => runProjectMutation(flags, Effect.fn("projectAddMutation")(function* ({ snapshot, dispatch }) {
|
|
36954
37635
|
const workspaceRoot = yield* normalizeWorkspaceRootForProjectCommand(flags.workspaceRoot);
|
|
36955
|
-
const existingProject = snapshot.projects.find((project) => project.deletedAt
|
|
37636
|
+
const existingProject = snapshot.projects.find((project) => project.deletedAt == null && project.workspaceRoot === workspaceRoot);
|
|
36956
37637
|
if (existingProject) return yield* new ProjectAlreadyExistsError({
|
|
36957
37638
|
operation: "addProject",
|
|
36958
37639
|
projectId: existingProject.id,
|
|
@@ -37919,7 +38600,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
|
|
|
37919
38600
|
filePath: error.filePath,
|
|
37920
38601
|
errorTag: error._tag
|
|
37921
38602
|
}));
|
|
37922
|
-
const make$
|
|
38603
|
+
const make$64 = Effect.gen(function* () {
|
|
37923
38604
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
37924
38605
|
const path = yield* Path.Path;
|
|
37925
38606
|
const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
|
|
@@ -37940,7 +38621,7 @@ const make$63 = Effect.gen(function* () {
|
|
|
37940
38621
|
});
|
|
37941
38622
|
return P4ProjectFileLoader.of({ load });
|
|
37942
38623
|
});
|
|
37943
|
-
const layer$52 = Layer.effect(P4ProjectFileLoader, make$
|
|
38624
|
+
const layer$52 = Layer.effect(P4ProjectFileLoader, make$64);
|
|
37944
38625
|
//#endregion
|
|
37945
38626
|
//#region src/project/ProjectFaviconResolver.ts
|
|
37946
38627
|
/**
|
|
@@ -38015,7 +38696,7 @@ function extractIconHref(source) {
|
|
|
38015
38696
|
return null;
|
|
38016
38697
|
}
|
|
38017
38698
|
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) }));
|
|
38018
|
-
const make$
|
|
38699
|
+
const make$63 = Effect.gen(function* () {
|
|
38019
38700
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
38020
38701
|
const path = yield* Path.Path;
|
|
38021
38702
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -38084,7 +38765,7 @@ const make$62 = Effect.gen(function* () {
|
|
|
38084
38765
|
});
|
|
38085
38766
|
return ProjectFaviconResolver.of({ resolvePath });
|
|
38086
38767
|
});
|
|
38087
|
-
const layer$51 = Layer.effect(ProjectFaviconResolver, make$
|
|
38768
|
+
const layer$51 = Layer.effect(ProjectFaviconResolver, make$63);
|
|
38088
38769
|
//#endregion
|
|
38089
38770
|
//#region src/assets/AssetAccess.ts
|
|
38090
38771
|
const ASSET_ROUTE_PREFIX = "/api/assets";
|
|
@@ -38495,10 +39176,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
|
|
|
38495
39176
|
//#endregion
|
|
38496
39177
|
//#region src/observability/BrowserTraceCollector.ts
|
|
38497
39178
|
var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
|
|
38498
|
-
const make$
|
|
39179
|
+
const make$62 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
|
|
38499
39180
|
for (const record of records) sink.push(record);
|
|
38500
39181
|
}) });
|
|
38501
|
-
const layer$50 = (sink) => Layer.succeed(BrowserTraceCollector, make$
|
|
39182
|
+
const layer$50 = (sink) => Layer.succeed(BrowserTraceCollector, make$62(sink));
|
|
38502
39183
|
//#endregion
|
|
38503
39184
|
//#region src/auth/http.ts
|
|
38504
39185
|
const CREDENTIAL_RESPONSE_HEADERS = {
|
|
@@ -39820,6 +40501,9 @@ const LIST_REFS_SNAPSHOT_CACHE_CAPACITY = 64;
|
|
|
39820
40501
|
const LIST_REFS_SNAPSHOT_CACHE_TTL = Duration.minutes(2);
|
|
39821
40502
|
const LIST_REFS_REFRESH_COALESCE_TTL = Duration.seconds(5);
|
|
39822
40503
|
const LIST_REFS_REFRESH_FAILURE_COOLDOWN = Duration.seconds(30);
|
|
40504
|
+
const STATUS_STATIC_CACHE_CAPACITY = 2048;
|
|
40505
|
+
const STATUS_DEFAULT_BRANCH_CACHE_TTL = Duration.minutes(5);
|
|
40506
|
+
const STATUS_ORIGIN_EXISTS_CACHE_TTL = Duration.minutes(5);
|
|
39823
40507
|
const STATUS_UPSTREAM_REFRESH_ENV = Object.freeze({
|
|
39824
40508
|
GCM_INTERACTIVE: "never",
|
|
39825
40509
|
GIT_ASKPASS: "",
|
|
@@ -40031,6 +40715,9 @@ function isMissingGitCwdError(error) {
|
|
|
40031
40715
|
function isNonRepositoryGitStderr(stderr) {
|
|
40032
40716
|
return stderr.toLowerCase().includes("not a git repository");
|
|
40033
40717
|
}
|
|
40718
|
+
function isUnbornHeadStderr(stderr) {
|
|
40719
|
+
return stderr.toLowerCase().includes("unknown revision") && stderr.toLowerCase().includes("path not in the working tree");
|
|
40720
|
+
}
|
|
40034
40721
|
const nowUnixNano = DateTime.now.pipe(Effect.map((now) => BigInt(DateTime.toEpochMillis(now)) * 1000000n));
|
|
40035
40722
|
const addCurrentSpanEvent = (name, attributes) => Effect.gen(function* () {
|
|
40036
40723
|
const span = yield* Effect.currentSpan;
|
|
@@ -40424,6 +41111,47 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40424
41111
|
const cacheKey = normalizeRepositoryPathsCacheKey(cwd);
|
|
40425
41112
|
return Cache.get(refresh ? repositoryPathsRefreshCache : repositoryPathsCache, cacheKey);
|
|
40426
41113
|
};
|
|
41114
|
+
const defaultBranchCache = yield* Cache.makeWith((gitCommonDir) => Effect.gen(function* () {
|
|
41115
|
+
const path = yield* Path.Path;
|
|
41116
|
+
const fetchCwd = path.basename(gitCommonDir) === ".git" ? path.dirname(gitCommonDir) : gitCommonDir;
|
|
41117
|
+
return yield* executeGit("GitVcsDriver.statusDetails.defaultBranch", fetchCwd, [
|
|
41118
|
+
"--git-dir",
|
|
41119
|
+
gitCommonDir,
|
|
41120
|
+
"symbolic-ref",
|
|
41121
|
+
"refs/remotes/origin/HEAD"
|
|
41122
|
+
], { allowNonZeroExit: true }).pipe(Effect.map((result) => {
|
|
41123
|
+
if (result.exitCode !== 0) return null;
|
|
41124
|
+
return parseDefaultBranchFromRemoteHeadRef(result.stdout, "origin");
|
|
41125
|
+
}));
|
|
41126
|
+
}), {
|
|
41127
|
+
capacity: STATUS_STATIC_CACHE_CAPACITY,
|
|
41128
|
+
timeToLive: Exit.match({
|
|
41129
|
+
onSuccess: () => STATUS_DEFAULT_BRANCH_CACHE_TTL,
|
|
41130
|
+
onFailure: () => Duration.zero
|
|
41131
|
+
})
|
|
41132
|
+
});
|
|
41133
|
+
const originExistsCache = yield* Cache.makeWith((gitCommonDir) => Effect.gen(function* () {
|
|
41134
|
+
const path = yield* Path.Path;
|
|
41135
|
+
const fetchCwd = path.basename(gitCommonDir) === ".git" ? path.dirname(gitCommonDir) : gitCommonDir;
|
|
41136
|
+
return yield* executeGit("GitVcsDriver.statusDetails.originExists", fetchCwd, [
|
|
41137
|
+
"--git-dir",
|
|
41138
|
+
gitCommonDir,
|
|
41139
|
+
"remote",
|
|
41140
|
+
"get-url",
|
|
41141
|
+
"origin"
|
|
41142
|
+
], { allowNonZeroExit: true }).pipe(Effect.map((result) => result.exitCode === 0));
|
|
41143
|
+
}), {
|
|
41144
|
+
capacity: STATUS_STATIC_CACHE_CAPACITY,
|
|
41145
|
+
timeToLive: Exit.match({
|
|
41146
|
+
onSuccess: () => STATUS_ORIGIN_EXISTS_CACHE_TTL,
|
|
41147
|
+
onFailure: () => Duration.zero
|
|
41148
|
+
})
|
|
41149
|
+
});
|
|
41150
|
+
const invalidateStatusStaticCaches = Effect.fn("invalidateStatusStaticCaches")(function* (cwd) {
|
|
41151
|
+
const cacheKey = (yield* resolveRepositoryPaths(cwd).pipe(Effect.catchTags({ GitCommandError: () => Effect.succeed(null) })))?.gitCommonDir ?? normalizeRepositoryPathsCacheKey(cwd);
|
|
41152
|
+
yield* Cache.invalidate(defaultBranchCache, cacheKey);
|
|
41153
|
+
yield* Cache.invalidate(originExistsCache, cacheKey);
|
|
41154
|
+
});
|
|
40427
41155
|
const resolveGitCommonDir = Effect.fn("resolveGitCommonDir")(function* (cwd) {
|
|
40428
41156
|
const repositoryPaths = yield* resolveRepositoryPaths(cwd);
|
|
40429
41157
|
if (repositoryPaths !== null) return repositoryPaths.gitCommonDir;
|
|
@@ -40467,10 +41195,16 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40467
41195
|
remoteName: upstream.remoteName
|
|
40468
41196
|
}));
|
|
40469
41197
|
});
|
|
40470
|
-
const resolveDefaultBranchName = (
|
|
40471
|
-
if (
|
|
40472
|
-
|
|
40473
|
-
|
|
41198
|
+
const resolveDefaultBranchName = Effect.fn("resolveDefaultBranchName")(function* (cwd, remoteName) {
|
|
41199
|
+
if (remoteName === "origin") {
|
|
41200
|
+
const repositoryPaths = yield* resolveRepositoryPaths(cwd);
|
|
41201
|
+
if (repositoryPaths) return yield* Cache.get(defaultBranchCache, repositoryPaths.gitCommonDir);
|
|
41202
|
+
}
|
|
41203
|
+
return yield* executeGit("GitVcsDriver.resolveDefaultBranchName", cwd, ["symbolic-ref", `refs/remotes/${remoteName}/HEAD`], { allowNonZeroExit: true }).pipe(Effect.map((result) => {
|
|
41204
|
+
if (result.exitCode !== 0) return null;
|
|
41205
|
+
return parseDefaultBranchFromRemoteHeadRef(result.stdout, remoteName);
|
|
41206
|
+
}));
|
|
41207
|
+
});
|
|
40474
41208
|
const remoteBranchExists = (cwd, remoteName, refName) => executeGit("GitVcsDriver.remoteBranchExists", cwd, [
|
|
40475
41209
|
"show-ref",
|
|
40476
41210
|
"--verify",
|
|
@@ -40575,9 +41309,10 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40575
41309
|
"HEAD"
|
|
40576
41310
|
], { allowNonZeroExit: true }).pipe(Effect.catchTags({ GitCommandError: (error) => isMissingGitCwdError(error) ? Effect.succeed(null) : Effect.fail(error) }));
|
|
40577
41311
|
if (branchResult === null) return NON_REPOSITORY_REMOTE_STATUS_DETAILS;
|
|
41312
|
+
let branch;
|
|
40578
41313
|
if (branchResult.exitCode !== 0) {
|
|
40579
41314
|
if (isNonRepositoryGitStderr(branchResult.stderr)) return NON_REPOSITORY_REMOTE_STATUS_DETAILS;
|
|
40580
|
-
return yield* new GitCommandError({
|
|
41315
|
+
if (!isUnbornHeadStderr(branchResult.stderr)) return yield* new GitCommandError({
|
|
40581
41316
|
...gitCommandContext({
|
|
40582
41317
|
operation: "GitVcsDriver.statusDetailsRemote.branch",
|
|
40583
41318
|
cwd,
|
|
@@ -40592,9 +41327,16 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40592
41327
|
stdoutLength: branchResult.stdout.length,
|
|
40593
41328
|
stderrLength: branchResult.stderr.length
|
|
40594
41329
|
});
|
|
41330
|
+
branch = (yield* runGitStdout("GitVcsDriver.statusDetailsRemote.unbornBranch", cwd, [
|
|
41331
|
+
"symbolic-ref",
|
|
41332
|
+
"--quiet",
|
|
41333
|
+
"--short",
|
|
41334
|
+
"HEAD"
|
|
41335
|
+
])).trim() || null;
|
|
41336
|
+
} else {
|
|
41337
|
+
const branchValue = branchResult.stdout.trim();
|
|
41338
|
+
branch = branchValue.length > 0 && branchValue !== "HEAD" ? branchValue : null;
|
|
40595
41339
|
}
|
|
40596
|
-
const branchValue = branchResult.stdout.trim();
|
|
40597
|
-
const branch = branchValue.length > 0 && branchValue !== "HEAD" ? branchValue : null;
|
|
40598
41340
|
const upstreamRef = (yield* resolveCurrentUpstream(cwd))?.upstreamRef ?? null;
|
|
40599
41341
|
let aheadCount = 0;
|
|
40600
41342
|
let behindCount = 0;
|
|
@@ -40652,18 +41394,53 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40652
41394
|
stderrLength: statusResult.stderr.length
|
|
40653
41395
|
});
|
|
40654
41396
|
}
|
|
40655
|
-
const
|
|
40656
|
-
|
|
40657
|
-
|
|
41397
|
+
const statusCacheKey = (yield* resolveRepositoryPaths(cwd).pipe(Effect.catchTags({ GitCommandError: () => Effect.succeed(null) })))?.gitCommonDir;
|
|
41398
|
+
const [numstatStdout, defaultBranch, hasPrimaryRemote] = yield* Effect.all([
|
|
41399
|
+
executeGitWithStableDiagnostics("GitVcsDriver.statusDetails.numstat", cwd, [
|
|
40658
41400
|
"diff",
|
|
40659
|
-
"
|
|
41401
|
+
"HEAD",
|
|
40660
41402
|
"--numstat"
|
|
40661
|
-
])
|
|
40662
|
-
|
|
40663
|
-
|
|
41403
|
+
], { allowNonZeroExit: true }).pipe(Effect.flatMap((result) => {
|
|
41404
|
+
if (result.exitCode === 0) return Effect.succeed(result.stdout);
|
|
41405
|
+
if (isUnbornHeadStderr(result.stderr)) return Effect.map(Effect.all([runGitStdout("GitVcsDriver.statusDetails.numstat.unborn", cwd, ["diff", "--numstat"]), runGitStdout("GitVcsDriver.statusDetails.numstat.unborn.staged", cwd, [
|
|
41406
|
+
"diff",
|
|
41407
|
+
"--cached",
|
|
41408
|
+
"--numstat"
|
|
41409
|
+
])]), ([unstagedStdout, stagedStdout]) => {
|
|
41410
|
+
const staged = parseNumstatEntries(stagedStdout);
|
|
41411
|
+
const unstaged = parseNumstatEntries(unstagedStdout);
|
|
41412
|
+
const map = /* @__PURE__ */ new Map();
|
|
41413
|
+
for (const entry of [...staged, ...unstaged]) {
|
|
41414
|
+
const existing = map.get(entry.path) ?? {
|
|
41415
|
+
insertions: 0,
|
|
41416
|
+
deletions: 0
|
|
41417
|
+
};
|
|
41418
|
+
existing.insertions += entry.insertions;
|
|
41419
|
+
existing.deletions += entry.deletions;
|
|
41420
|
+
map.set(entry.path, existing);
|
|
41421
|
+
}
|
|
41422
|
+
return Array.from(map.entries()).map(([p, s]) => `${s.insertions}\t${s.deletions}\t${p}`).join("\n");
|
|
41423
|
+
});
|
|
41424
|
+
return Effect.fail(new GitCommandError({
|
|
41425
|
+
...gitCommandContext({
|
|
41426
|
+
operation: "GitVcsDriver.statusDetails.numstat",
|
|
41427
|
+
cwd,
|
|
41428
|
+
args: [
|
|
41429
|
+
"diff",
|
|
41430
|
+
"HEAD",
|
|
41431
|
+
"--numstat"
|
|
41432
|
+
]
|
|
41433
|
+
}),
|
|
41434
|
+
detail: "git diff HEAD --numstat failed.",
|
|
41435
|
+
exitCode: result.exitCode,
|
|
41436
|
+
stdoutLength: result.stdout.length,
|
|
41437
|
+
stderrLength: result.stderr.length
|
|
41438
|
+
}));
|
|
41439
|
+
})),
|
|
41440
|
+
statusCacheKey ? Cache.get(defaultBranchCache, statusCacheKey).pipe(Effect.orElseSucceed(() => null)) : resolveDefaultBranchName(cwd, "origin").pipe(Effect.orElseSucceed(() => null)),
|
|
41441
|
+
statusCacheKey ? Cache.get(originExistsCache, statusCacheKey).pipe(Effect.orElseSucceed(() => false)) : originRemoteExists(cwd).pipe(Effect.orElseSucceed(() => false))
|
|
40664
41442
|
], { concurrency: "unbounded" });
|
|
40665
41443
|
const statusStdout = statusResult.stdout;
|
|
40666
|
-
const defaultBranch = defaultRefResult.exitCode === 0 ? defaultRefResult.stdout.trim().replace(/^refs\/remotes\/origin\//, "") : null;
|
|
40667
41444
|
let refName = null;
|
|
40668
41445
|
let upstreamRef = null;
|
|
40669
41446
|
let aheadCount = 0;
|
|
@@ -40701,18 +41478,12 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
40701
41478
|
}
|
|
40702
41479
|
const isDefaultBranch = refName !== null && (refName === defaultBranch || defaultBranch === null && (refName === "main" || refName === "master"));
|
|
40703
41480
|
if (refName && !isDefaultBranch) aheadOfDefaultCount = fallbackAheadCount !== null ? fallbackAheadCount : yield* computeAheadCountAgainstBase(cwd, refName).pipe(Effect.orElseSucceed(() => 0));
|
|
40704
|
-
const
|
|
40705
|
-
const unstagedEntries = parseNumstatEntries(unstagedNumstatStdout);
|
|
41481
|
+
const numstatEntries = parseNumstatEntries(numstatStdout);
|
|
40706
41482
|
const fileStatMap = /* @__PURE__ */ new Map();
|
|
40707
|
-
for (const entry of
|
|
40708
|
-
|
|
40709
|
-
|
|
40710
|
-
|
|
40711
|
-
};
|
|
40712
|
-
existing.insertions += entry.insertions;
|
|
40713
|
-
existing.deletions += entry.deletions;
|
|
40714
|
-
fileStatMap.set(entry.path, existing);
|
|
40715
|
-
}
|
|
41483
|
+
for (const entry of numstatEntries) fileStatMap.set(entry.path, {
|
|
41484
|
+
insertions: entry.insertions,
|
|
41485
|
+
deletions: entry.deletions
|
|
41486
|
+
});
|
|
40716
41487
|
let insertions = 0;
|
|
40717
41488
|
let deletions = 0;
|
|
40718
41489
|
const files = Array.from(fileStatMap.entries()).map(([filePath, stat]) => {
|
|
@@ -41525,7 +42296,7 @@ const makeGitVcsDriverCore = Effect.fn("makeGitVcsDriverCore")(function* () {
|
|
|
41525
42296
|
}
|
|
41526
42297
|
return branchNames;
|
|
41527
42298
|
}));
|
|
41528
|
-
const withListRefsInvalidation = (cwd, effect) => effect.pipe(Effect.ensuring(invalidateListRefsSnapshot(cwd).pipe(Effect.ignore)));
|
|
42299
|
+
const withListRefsInvalidation = (cwd, effect) => effect.pipe(Effect.ensuring(Effect.all([invalidateListRefsSnapshot(cwd).pipe(Effect.ignore), invalidateStatusStaticCaches(cwd).pipe(Effect.ignore)])));
|
|
41529
42300
|
const initRepoWithListRefsInvalidation = (input) => initRepo(input).pipe(Effect.ensuring(Effect.gen(function* () {
|
|
41530
42301
|
const cacheKey = normalizeRepositoryPathsCacheKey(input.cwd);
|
|
41531
42302
|
yield* Cache.invalidate(repositoryPathsRefreshCache, cacheKey);
|
|
@@ -41576,7 +42347,7 @@ const classifyNonZeroExit = (command, stderr) => {
|
|
|
41576
42347
|
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";
|
|
41577
42348
|
return "command-failed";
|
|
41578
42349
|
};
|
|
41579
|
-
const make$
|
|
42350
|
+
const make$61 = Effect.gen(function* () {
|
|
41580
42351
|
const processRunner = yield* ProcessRunner;
|
|
41581
42352
|
const run = Effect.fn("VcsProcess.run")(function* (input) {
|
|
41582
42353
|
const baseError = {
|
|
@@ -41635,7 +42406,7 @@ const make$60 = Effect.gen(function* () {
|
|
|
41635
42406
|
});
|
|
41636
42407
|
return VcsProcess.of({ run });
|
|
41637
42408
|
});
|
|
41638
|
-
const layer$49 = Layer.effect(VcsProcess, make$
|
|
42409
|
+
const layer$49 = Layer.effect(VcsProcess, make$61).pipe(Layer.provide(layer$63));
|
|
41639
42410
|
//#endregion
|
|
41640
42411
|
//#region src/vcs/VcsDriver.ts
|
|
41641
42412
|
var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
|
|
@@ -42086,12 +42857,12 @@ const makeVcsDriver = Effect.gen(function* () {
|
|
|
42086
42857
|
const driver = yield* makeVcsDriverShape();
|
|
42087
42858
|
return VcsDriver.of(driver);
|
|
42088
42859
|
});
|
|
42089
|
-
const make$
|
|
42860
|
+
const make$60 = Effect.gen(function* () {
|
|
42090
42861
|
const git = yield* makeGitVcsDriverCore();
|
|
42091
42862
|
return GitVcsDriver.of(git);
|
|
42092
42863
|
});
|
|
42093
42864
|
Layer.effect(VcsDriver, makeVcsDriver);
|
|
42094
|
-
const layer$48 = Layer.effect(GitVcsDriver, make$
|
|
42865
|
+
const layer$48 = Layer.effect(GitVcsDriver, make$60);
|
|
42095
42866
|
//#endregion
|
|
42096
42867
|
//#region src/vcs/VcsProjectConfig.ts
|
|
42097
42868
|
const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
|
|
@@ -42123,7 +42894,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
|
|
|
42123
42894
|
configPath: error.configPath,
|
|
42124
42895
|
errorTag: error._tag
|
|
42125
42896
|
}));
|
|
42126
|
-
const make$
|
|
42897
|
+
const make$59 = Effect.gen(function* () {
|
|
42127
42898
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
42128
42899
|
const path = yield* Path.Path;
|
|
42129
42900
|
const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
|
|
@@ -42164,7 +42935,7 @@ const make$58 = Effect.gen(function* () {
|
|
|
42164
42935
|
});
|
|
42165
42936
|
return VcsProjectConfig.of({ resolveKind });
|
|
42166
42937
|
});
|
|
42167
|
-
const layer$47 = Layer.effect(VcsProjectConfig, make$
|
|
42938
|
+
const layer$47 = Layer.effect(VcsProjectConfig, make$59);
|
|
42168
42939
|
//#endregion
|
|
42169
42940
|
//#region src/vcs/VcsDriverRegistry.ts
|
|
42170
42941
|
const DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -42184,7 +42955,7 @@ function parseDetectionCacheKey(key) {
|
|
|
42184
42955
|
cwd: key.slice(separatorIndex + 1)
|
|
42185
42956
|
};
|
|
42186
42957
|
}
|
|
42187
|
-
const make$
|
|
42958
|
+
const make$58 = Effect.gen(function* () {
|
|
42188
42959
|
const projectConfig = yield* VcsProjectConfig;
|
|
42189
42960
|
const git = yield* makeVcsDriver;
|
|
42190
42961
|
const drivers = { git };
|
|
@@ -42241,7 +43012,7 @@ const make$57 = Effect.gen(function* () {
|
|
|
42241
43012
|
resolve
|
|
42242
43013
|
});
|
|
42243
43014
|
});
|
|
42244
|
-
const layer$46 = Layer.effect(VcsDriverRegistry, make$
|
|
43015
|
+
const layer$46 = Layer.effect(VcsDriverRegistry, make$58).pipe(Layer.provide(layer$47));
|
|
42245
43016
|
//#endregion
|
|
42246
43017
|
//#region src/checkpointing/CheckpointStore.ts
|
|
42247
43018
|
/**
|
|
@@ -42261,7 +43032,7 @@ const layer$46 = Layer.effect(VcsDriverRegistry, make$57).pipe(Layer.provide(lay
|
|
|
42261
43032
|
*/
|
|
42262
43033
|
/** Service tag for checkpoint persistence and restore operations. */
|
|
42263
43034
|
var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
|
|
42264
|
-
const make$
|
|
43035
|
+
const make$57 = Effect.gen(function* () {
|
|
42265
43036
|
const vcsRegistry = yield* VcsDriverRegistry;
|
|
42266
43037
|
const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
|
|
42267
43038
|
const handle = yield* vcsRegistry.resolve({ cwd });
|
|
@@ -42300,7 +43071,7 @@ const make$56 = Effect.gen(function* () {
|
|
|
42300
43071
|
deleteCheckpointRefs
|
|
42301
43072
|
});
|
|
42302
43073
|
});
|
|
42303
|
-
const layer$45 = Layer.effect(CheckpointStore, make$
|
|
43074
|
+
const layer$45 = Layer.effect(CheckpointStore, make$57);
|
|
42304
43075
|
//#endregion
|
|
42305
43076
|
//#region src/checkpointing/CheckpointDiffQuery.ts
|
|
42306
43077
|
/**
|
|
@@ -42322,7 +43093,7 @@ function buildTurnDiffResult(input, diff) {
|
|
|
42322
43093
|
diff
|
|
42323
43094
|
};
|
|
42324
43095
|
}
|
|
42325
|
-
const make$
|
|
43096
|
+
const make$56 = Effect.gen(function* () {
|
|
42326
43097
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
42327
43098
|
const checkpointStore = yield* CheckpointStore;
|
|
42328
43099
|
const threadActivities = yield* ProjectionThreadActivityRepository;
|
|
@@ -42493,7 +43264,7 @@ const make$55 = Effect.gen(function* () {
|
|
|
42493
43264
|
getFullThreadDiff
|
|
42494
43265
|
});
|
|
42495
43266
|
});
|
|
42496
|
-
const layer$44 = Layer.effect(CheckpointDiffQuery, make$
|
|
43267
|
+
const layer$44 = Layer.effect(CheckpointDiffQuery, make$56);
|
|
42497
43268
|
//#endregion
|
|
42498
43269
|
//#region src/orchestration/ThreadLiveEventCoalescer.ts
|
|
42499
43270
|
const COALESCE_WINDOW = Duration.millis(50);
|
|
@@ -42728,11 +43499,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
|
|
|
42728
43499
|
detail: "This provider does not report account usage."
|
|
42729
43500
|
}))))
|
|
42730
43501
|
});
|
|
42731
|
-
const make$
|
|
43502
|
+
const make$55 = Effect.gen(function* () {
|
|
42732
43503
|
const registry = yield* ProviderInstanceRegistry;
|
|
42733
43504
|
return makeTextGenerationFromRegistry(registry);
|
|
42734
43505
|
});
|
|
42735
|
-
const layer$43 = Layer.effect(TextGeneration, make$
|
|
43506
|
+
const layer$43 = Layer.effect(TextGeneration, make$55);
|
|
42736
43507
|
//#endregion
|
|
42737
43508
|
//#region src/textGeneration/TextGenerationPresets.ts
|
|
42738
43509
|
const conventionalCommitsTextGenerationPolicy = {
|
|
@@ -43064,7 +43835,7 @@ const serversEqual = (left, right) => {
|
|
|
43064
43835
|
}
|
|
43065
43836
|
return true;
|
|
43066
43837
|
};
|
|
43067
|
-
const make$
|
|
43838
|
+
const make$54 = Effect.gen(function* PortDiscoveryMake() {
|
|
43068
43839
|
const net = yield* NetService;
|
|
43069
43840
|
const processRunner = yield* ProcessRunner;
|
|
43070
43841
|
const hostPlatform = yield* HostProcessPlatform;
|
|
@@ -43215,7 +43986,7 @@ const make$53 = Effect.gen(function* PortDiscoveryMake() {
|
|
|
43215
43986
|
unregisterTerminal
|
|
43216
43987
|
});
|
|
43217
43988
|
}).pipe(Effect.withSpan("PortDiscovery.make"));
|
|
43218
|
-
const layer$42 = Layer.effect(PortDiscovery, make$
|
|
43989
|
+
const layer$42 = Layer.effect(PortDiscovery, make$54);
|
|
43219
43990
|
//#endregion
|
|
43220
43991
|
//#region src/terminal/Manager.ts
|
|
43221
43992
|
/**
|
|
@@ -43893,7 +44664,7 @@ function normalizedRuntimeEnv(env) {
|
|
|
43893
44664
|
if (entries.length === 0) return null;
|
|
43894
44665
|
return Object.fromEntries(entries.toSorted(([left], [right]) => left.localeCompare(right)));
|
|
43895
44666
|
}
|
|
43896
|
-
const make$
|
|
44667
|
+
const make$53 = Effect.fn("TerminalManager.make")(function* () {
|
|
43897
44668
|
const { terminalLogsDir } = yield* ServerConfig$1;
|
|
43898
44669
|
const ptyAdapter = yield* PtyAdapter;
|
|
43899
44670
|
const portDiscovery = yield* PortDiscovery;
|
|
@@ -44855,7 +45626,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
|
|
|
44855
45626
|
subscribeMetadata
|
|
44856
45627
|
});
|
|
44857
45628
|
});
|
|
44858
|
-
const layer$41 = Layer.effect(TerminalManager, make$
|
|
45629
|
+
const layer$41 = Layer.effect(TerminalManager, make$53()).pipe(Layer.provide(layer$63));
|
|
44859
45630
|
//#endregion
|
|
44860
45631
|
//#region src/project/ProjectSetupScriptRunner.ts
|
|
44861
45632
|
var ProjectSetupScriptOperationError = class extends Schema$1.TaggedErrorClass()("ProjectSetupScriptOperationError", {
|
|
@@ -44886,7 +45657,7 @@ var ProjectSetupScriptProjectNotFoundError = class extends Schema$1.TaggedErrorC
|
|
|
44886
45657
|
};
|
|
44887
45658
|
Schema$1.Union([ProjectSetupScriptOperationError, ProjectSetupScriptProjectNotFoundError]);
|
|
44888
45659
|
var ProjectSetupScriptRunner = class extends Context.Service()("@p4code/cli/project/ProjectSetupScriptRunner") {};
|
|
44889
|
-
const make$
|
|
45660
|
+
const make$52 = Effect.gen(function* () {
|
|
44890
45661
|
const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
|
|
44891
45662
|
const terminalManager = yield* TerminalManager;
|
|
44892
45663
|
const runForThread = Effect.fn("ProjectSetupScriptRunner.runForThread")(function* (input) {
|
|
@@ -44944,7 +45715,7 @@ const make$51 = Effect.gen(function* () {
|
|
|
44944
45715
|
});
|
|
44945
45716
|
return ProjectSetupScriptRunner.of({ runForThread });
|
|
44946
45717
|
});
|
|
44947
|
-
const layer$40 = Layer.effect(ProjectSetupScriptRunner, make$
|
|
45718
|
+
const layer$40 = Layer.effect(ProjectSetupScriptRunner, make$52);
|
|
44948
45719
|
//#endregion
|
|
44949
45720
|
//#region src/provider/Services/ProviderRegistry.ts
|
|
44950
45721
|
var ProviderRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderRegistry") {};
|
|
@@ -45041,19 +45812,23 @@ function normalizeAzureDevOpsPullRequestRecord(raw) {
|
|
|
45041
45812
|
baseRefName: normalizeRefName$1(raw.targetRefName),
|
|
45042
45813
|
headRefName: normalizeRefName$1(raw.sourceRefName),
|
|
45043
45814
|
state: normalizeAzureDevOpsPullRequestState(raw.status),
|
|
45815
|
+
...Option.isSome(raw.closedDate ?? Option.none()) ? { terminalAt: DateTime.formatIso(Option.getOrThrow(raw.closedDate ?? Option.none())) } : {},
|
|
45044
45816
|
updatedAt: (raw.closedDate ?? Option.none()).pipe(Option.orElse(() => raw.creationDate ?? Option.none()))
|
|
45045
45817
|
};
|
|
45046
45818
|
}
|
|
45047
45819
|
const decodeAzureDevOpsPullRequestList = decodeJsonResult(Schema$1.Array(Schema$1.Unknown));
|
|
45048
45820
|
const decodeAzureDevOpsPullRequest = decodeJsonResult(AzureDevOpsPullRequestSchema);
|
|
45049
45821
|
const decodeAzureDevOpsPullRequestEntry = Schema$1.decodeUnknownExit(AzureDevOpsPullRequestSchema);
|
|
45050
|
-
function decodeAzureDevOpsPullRequestListJson(raw) {
|
|
45822
|
+
function decodeAzureDevOpsPullRequestListJson(raw, strict = false) {
|
|
45051
45823
|
const result = decodeAzureDevOpsPullRequestList(raw);
|
|
45052
45824
|
if (Result.isSuccess(result)) {
|
|
45053
45825
|
const pullRequests = [];
|
|
45054
45826
|
for (const entry of result.success) {
|
|
45055
45827
|
const decodedEntry = decodeAzureDevOpsPullRequestEntry(entry);
|
|
45056
|
-
if (Exit.isFailure(decodedEntry))
|
|
45828
|
+
if (Exit.isFailure(decodedEntry)) {
|
|
45829
|
+
if (strict) return Result.fail(decodedEntry.cause);
|
|
45830
|
+
continue;
|
|
45831
|
+
}
|
|
45057
45832
|
pullRequests.push(normalizeAzureDevOpsPullRequestRecord(decodedEntry.value));
|
|
45058
45833
|
}
|
|
45059
45834
|
return Result.succeed(pullRequests);
|
|
@@ -45271,7 +46046,7 @@ function decodeAzureDevOpsJson(raw, schema, operation, cwd) {
|
|
|
45271
46046
|
cause
|
|
45272
46047
|
})));
|
|
45273
46048
|
}
|
|
45274
|
-
const make$
|
|
46049
|
+
const make$51 = Effect.gen(function* () {
|
|
45275
46050
|
const process = yield* VcsProcess;
|
|
45276
46051
|
const execute = (input) => process.run({
|
|
45277
46052
|
operation: "AzureDevOpsCli.execute",
|
|
@@ -45311,7 +46086,7 @@ const make$50 = Effect.gen(function* () {
|
|
|
45311
46086
|
"--top",
|
|
45312
46087
|
String(input.limit ?? 20)
|
|
45313
46088
|
]
|
|
45314
|
-
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => raw.length === 0 ? Effect.succeed([]) : Effect.sync(() => decodeAzureDevOpsPullRequestListJson(raw)).pipe(Effect.flatMap((decoded) => {
|
|
46089
|
+
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => raw.length === 0 && !input.strict ? Effect.succeed([]) : Effect.sync(() => decodeAzureDevOpsPullRequestListJson(raw, input.strict)).pipe(Effect.flatMap((decoded) => {
|
|
45315
46090
|
if (!Result.isSuccess(decoded)) return Effect.fail(new AzureDevOpsPullRequestListDecodeError({
|
|
45316
46091
|
operation: "listPullRequests",
|
|
45317
46092
|
command: "az",
|
|
@@ -45413,7 +46188,7 @@ const make$50 = Effect.gen(function* () {
|
|
|
45413
46188
|
}).pipe(Effect.asVoid)
|
|
45414
46189
|
});
|
|
45415
46190
|
});
|
|
45416
|
-
const layer$39 = Layer.effect(AzureDevOpsCli, make$
|
|
46191
|
+
const layer$39 = Layer.effect(AzureDevOpsCli, make$51);
|
|
45417
46192
|
//#endregion
|
|
45418
46193
|
//#region src/sourceControl/SourceControlProviderDiscovery.ts
|
|
45419
46194
|
function firstNonEmptyLine(text) {
|
|
@@ -45613,10 +46388,11 @@ function toChangeRequest$5(summary) {
|
|
|
45613
46388
|
headRefName: summary.headRefName,
|
|
45614
46389
|
state: summary.state,
|
|
45615
46390
|
updatedAt: summary.updatedAt,
|
|
46391
|
+
...summary.terminalAt == null ? {} : { terminalAt: summary.terminalAt },
|
|
45616
46392
|
isCrossRepository: false
|
|
45617
46393
|
};
|
|
45618
46394
|
}
|
|
45619
|
-
const make$
|
|
46395
|
+
const make$50 = Effect.gen(function* () {
|
|
45620
46396
|
const azure = yield* AzureDevOpsCli;
|
|
45621
46397
|
return SourceControlProvider.of({
|
|
45622
46398
|
kind: "azure-devops",
|
|
@@ -45627,6 +46403,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
45627
46403
|
headSelector: input.headSelector,
|
|
45628
46404
|
...source !== void 0 ? { source } : {},
|
|
45629
46405
|
state: input.state,
|
|
46406
|
+
...input.strict !== void 0 ? { strict: input.strict } : {},
|
|
45630
46407
|
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
45631
46408
|
}).pipe(Effect.map((items) => items.map(toChangeRequest$5)), Effect.mapError((error) => new SourceControlProviderError({
|
|
45632
46409
|
provider: "azure-devops",
|
|
@@ -45708,7 +46485,7 @@ const make$49 = Effect.gen(function* () {
|
|
|
45708
46485
|
})))
|
|
45709
46486
|
});
|
|
45710
46487
|
});
|
|
45711
|
-
Layer.effect(SourceControlProvider, make$
|
|
46488
|
+
Layer.effect(SourceControlProvider, make$50);
|
|
45712
46489
|
//#endregion
|
|
45713
46490
|
//#region src/sourceControl/bitbucketPullRequests.ts
|
|
45714
46491
|
const BitbucketRepositoryRefSchema = Schema$1.Struct({
|
|
@@ -46085,7 +46862,7 @@ function responseError(operation, response) {
|
|
|
46085
46862
|
responseBodyLength: collected.text.length
|
|
46086
46863
|
}))));
|
|
46087
46864
|
}
|
|
46088
|
-
const make$
|
|
46865
|
+
const make$49 = Effect.gen(function* () {
|
|
46089
46866
|
const config = yield* BitbucketApiEnvConfig;
|
|
46090
46867
|
const httpClient = yield* HttpClient.HttpClient;
|
|
46091
46868
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
@@ -46301,7 +47078,7 @@ const make$48 = Effect.gen(function* () {
|
|
|
46301
47078
|
})))
|
|
46302
47079
|
});
|
|
46303
47080
|
});
|
|
46304
|
-
const layer$37 = Layer.effect(BitbucketApi, make$
|
|
47081
|
+
const layer$37 = Layer.effect(BitbucketApi, make$49);
|
|
46305
47082
|
//#endregion
|
|
46306
47083
|
//#region src/sourceControl/BitbucketSourceControlProvider.ts
|
|
46307
47084
|
function toChangeRequest$4(summary) {
|
|
@@ -46319,7 +47096,7 @@ function toChangeRequest$4(summary) {
|
|
|
46319
47096
|
...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
|
|
46320
47097
|
};
|
|
46321
47098
|
}
|
|
46322
|
-
const make$
|
|
47099
|
+
const make$48 = Effect.gen(function* () {
|
|
46323
47100
|
const bitbucket = yield* BitbucketApi;
|
|
46324
47101
|
return SourceControlProvider.of({
|
|
46325
47102
|
kind: "bitbucket",
|
|
@@ -46410,7 +47187,7 @@ const make$47 = Effect.gen(function* () {
|
|
|
46410
47187
|
})))
|
|
46411
47188
|
});
|
|
46412
47189
|
});
|
|
46413
|
-
Layer.effect(SourceControlProvider, make$
|
|
47190
|
+
Layer.effect(SourceControlProvider, make$48);
|
|
46414
47191
|
const makeDiscovery = Effect.gen(function* () {
|
|
46415
47192
|
return {
|
|
46416
47193
|
type: "api",
|
|
@@ -46430,6 +47207,7 @@ const GitHubPullRequestSchema = Schema$1.Struct({
|
|
|
46430
47207
|
headRefName: TrimmedNonEmptyString,
|
|
46431
47208
|
state: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
46432
47209
|
mergedAt: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
47210
|
+
closedAt: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
46433
47211
|
updatedAt: Schema$1.optional(Schema$1.OptionFromNullOr(Schema$1.DateTimeUtcFromString)),
|
|
46434
47212
|
isCrossRepository: Schema$1.optional(Schema$1.Boolean),
|
|
46435
47213
|
headRepository: Schema$1.optional(Schema$1.NullOr(Schema$1.Struct({
|
|
@@ -46453,6 +47231,7 @@ function normalizeGitHubPullRequestRecord(raw) {
|
|
|
46453
47231
|
const headRepositoryName = trimOptionalString$1(raw.headRepository?.name);
|
|
46454
47232
|
const headRepositoryOwnerLogin = trimOptionalString$1(raw.headRepositoryOwner?.login) ?? (explicitNameWithOwner?.includes("/") ? explicitNameWithOwner.split("/")[0] ?? null : null);
|
|
46455
47233
|
const headRepositoryNameWithOwner = explicitNameWithOwner ?? (headRepositoryOwnerLogin && headRepositoryName ? `${headRepositoryOwnerLogin}/${headRepositoryName}` : null);
|
|
47234
|
+
const terminalAt = normalizeGitHubPullRequestState(raw) === "merged" ? raw.mergedAt ?? null : normalizeGitHubPullRequestState(raw) === "closed" ? raw.closedAt ?? null : null;
|
|
46456
47235
|
return {
|
|
46457
47236
|
number: raw.number,
|
|
46458
47237
|
title: raw.title,
|
|
@@ -46461,6 +47240,7 @@ function normalizeGitHubPullRequestRecord(raw) {
|
|
|
46461
47240
|
headRefName: raw.headRefName,
|
|
46462
47241
|
state: normalizeGitHubPullRequestState(raw),
|
|
46463
47242
|
updatedAt: raw.updatedAt ?? Option.none(),
|
|
47243
|
+
...terminalAt == null ? {} : { terminalAt },
|
|
46464
47244
|
...typeof raw.isCrossRepository === "boolean" ? { isCrossRepository: raw.isCrossRepository } : {},
|
|
46465
47245
|
...headRepositoryNameWithOwner ? { headRepositoryNameWithOwner } : {},
|
|
46466
47246
|
...headRepositoryOwnerLogin ? { headRepositoryOwnerLogin } : {}
|
|
@@ -46469,13 +47249,16 @@ function normalizeGitHubPullRequestRecord(raw) {
|
|
|
46469
47249
|
const decodeGitHubPullRequestList = decodeJsonResult(Schema$1.Array(Schema$1.Unknown));
|
|
46470
47250
|
const decodeGitHubPullRequest = decodeJsonResult(GitHubPullRequestSchema);
|
|
46471
47251
|
const decodeGitHubPullRequestEntry = Schema$1.decodeUnknownExit(GitHubPullRequestSchema);
|
|
46472
|
-
function decodeGitHubPullRequestListJson(raw) {
|
|
47252
|
+
function decodeGitHubPullRequestListJson(raw, strict = false) {
|
|
46473
47253
|
const result = decodeGitHubPullRequestList(raw);
|
|
46474
47254
|
if (Result.isSuccess(result)) {
|
|
46475
47255
|
const pullRequests = [];
|
|
46476
47256
|
for (const entry of result.success) {
|
|
46477
47257
|
const decodedEntry = decodeGitHubPullRequestEntry(entry);
|
|
46478
|
-
if (Exit.isFailure(decodedEntry))
|
|
47258
|
+
if (Exit.isFailure(decodedEntry)) {
|
|
47259
|
+
if (strict) return Result.fail(decodedEntry.cause);
|
|
47260
|
+
continue;
|
|
47261
|
+
}
|
|
46479
47262
|
pullRequests.push(normalizeGitHubPullRequestRecord(decodedEntry.value));
|
|
46480
47263
|
}
|
|
46481
47264
|
return Result.succeed(pullRequests);
|
|
@@ -46652,7 +47435,7 @@ function deriveRepositoryCloneUrlsFromCreateOutput(stdout, repository) {
|
|
|
46652
47435
|
sshUrl: `git@${fallbackHost}:${repository}.git`
|
|
46653
47436
|
};
|
|
46654
47437
|
}
|
|
46655
|
-
const make$
|
|
47438
|
+
const make$47 = Effect.gen(function* () {
|
|
46656
47439
|
const process = yield* VcsProcess;
|
|
46657
47440
|
const execute = (input) => process.run({
|
|
46658
47441
|
operation: "GitHubCli.execute",
|
|
@@ -46680,7 +47463,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
46680
47463
|
"--limit",
|
|
46681
47464
|
String(input.limit ?? 1),
|
|
46682
47465
|
"--json",
|
|
46683
|
-
"number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
47466
|
+
"number,title,url,baseRefName,headRefName,state,mergedAt,closedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
46684
47467
|
]
|
|
46685
47468
|
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => raw.length === 0 ? Effect.succeed([]) : Effect.sync(() => decodeGitHubPullRequestListJson(raw)).pipe(Effect.flatMap((decoded) => {
|
|
46686
47469
|
if (!Result.isSuccess(decoded)) return Effect.fail(new GitHubPullRequestListDecodeError({
|
|
@@ -46697,7 +47480,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
46697
47480
|
"view",
|
|
46698
47481
|
input.reference,
|
|
46699
47482
|
"--json",
|
|
46700
|
-
"number,title,url,baseRefName,headRefName,state,mergedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
47483
|
+
"number,title,url,baseRefName,headRefName,state,mergedAt,closedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
46701
47484
|
]
|
|
46702
47485
|
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => Effect.sync(() => decodeGitHubPullRequestJson(raw)).pipe(Effect.flatMap((decoded) => {
|
|
46703
47486
|
if (!Result.isSuccess(decoded)) return Effect.fail(new GitHubPullRequestDecodeError({
|
|
@@ -46770,7 +47553,7 @@ const make$46 = Effect.gen(function* () {
|
|
|
46770
47553
|
}).pipe(Effect.asVoid)
|
|
46771
47554
|
});
|
|
46772
47555
|
});
|
|
46773
|
-
const layer$35 = Layer.effect(GitHubCli, make$
|
|
47556
|
+
const layer$35 = Layer.effect(GitHubCli, make$47);
|
|
46774
47557
|
//#endregion
|
|
46775
47558
|
//#region src/sourceControl/gitHubAuthStatus.ts
|
|
46776
47559
|
const GitHubAuthStatusAccountSchema = Schema$1.Struct({
|
|
@@ -46824,6 +47607,7 @@ function toChangeRequest$3(summary) {
|
|
|
46824
47607
|
headRefName: summary.headRefName,
|
|
46825
47608
|
state: summary.state ?? "open",
|
|
46826
47609
|
updatedAt: Option.none(),
|
|
47610
|
+
...summary.terminalAt == null ? {} : { terminalAt: summary.terminalAt },
|
|
46827
47611
|
...summary.isCrossRepository !== void 0 ? { isCrossRepository: summary.isCrossRepository } : {},
|
|
46828
47612
|
...summary.headRepositoryNameWithOwner !== void 0 ? { headRepositoryNameWithOwner: summary.headRepositoryNameWithOwner } : {},
|
|
46829
47613
|
...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
|
|
@@ -46871,7 +47655,7 @@ const discovery$1 = {
|
|
|
46871
47655
|
parseAuth: parseGitHubAuth,
|
|
46872
47656
|
installHint: "Install the GitHub command-line tool (`gh`) via https://cli.github.com/ or your package manager (for example `brew install gh`)."
|
|
46873
47657
|
};
|
|
46874
|
-
const make$
|
|
47658
|
+
const make$46 = Effect.gen(function* () {
|
|
46875
47659
|
const github = yield* GitHubCli;
|
|
46876
47660
|
const listChangeRequests = (input) => {
|
|
46877
47661
|
if (input.state === "open") return github.listOpenPullRequests({
|
|
@@ -46900,12 +47684,12 @@ const make$45 = Effect.gen(function* () {
|
|
|
46900
47684
|
"--limit",
|
|
46901
47685
|
String(input.limit ?? 20),
|
|
46902
47686
|
"--json",
|
|
46903
|
-
"number,title,url,baseRefName,headRefName,state,mergedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
47687
|
+
"number,title,url,baseRefName,headRefName,state,mergedAt,closedAt,updatedAt,isCrossRepository,headRepository,headRepositoryOwner"
|
|
46904
47688
|
]
|
|
46905
47689
|
}).pipe(Effect.flatMap((result) => {
|
|
46906
47690
|
const raw = result.stdout.trim();
|
|
46907
|
-
if (raw.length === 0) return Effect.succeed([]);
|
|
46908
|
-
return Effect.sync(() => decodeGitHubPullRequestListJson(raw)).pipe(Effect.flatMap((decoded) => Result.isSuccess(decoded) ? Effect.succeed(decoded.success.map((item) => ({
|
|
47691
|
+
if (raw.length === 0 && !input.strict) return Effect.succeed([]);
|
|
47692
|
+
return Effect.sync(() => decodeGitHubPullRequestListJson(raw, input.strict)).pipe(Effect.flatMap((decoded) => Result.isSuccess(decoded) ? Effect.succeed(decoded.success.map((item) => ({
|
|
46909
47693
|
...toChangeRequest$3(item),
|
|
46910
47694
|
updatedAt: item.updatedAt
|
|
46911
47695
|
}))) : Effect.fail(new GitHubChangeRequestListDecodeError({
|
|
@@ -46987,7 +47771,7 @@ const make$45 = Effect.gen(function* () {
|
|
|
46987
47771
|
})))
|
|
46988
47772
|
});
|
|
46989
47773
|
});
|
|
46990
|
-
Layer.effect(SourceControlProvider, make$
|
|
47774
|
+
Layer.effect(SourceControlProvider, make$46);
|
|
46991
47775
|
//#endregion
|
|
46992
47776
|
//#region src/sourceControl/gitLabMergeRequests.ts
|
|
46993
47777
|
const GitLabProjectReferenceSchema = Schema$1.Struct({
|
|
@@ -47006,6 +47790,8 @@ const GitLabMergeRequestSchema = Schema$1.Struct({
|
|
|
47006
47790
|
source_branch: TrimmedNonEmptyString,
|
|
47007
47791
|
target_branch: TrimmedNonEmptyString,
|
|
47008
47792
|
state: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
47793
|
+
merged_at: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
47794
|
+
closed_at: Schema$1.optional(Schema$1.NullOr(Schema$1.String)),
|
|
47009
47795
|
updated_at: Schema$1.optional(Schema$1.OptionFromNullOr(Schema$1.DateTimeUtcFromString)),
|
|
47010
47796
|
source_project_id: Schema$1.optional(Schema$1.NullOr(Schema$1.Number)),
|
|
47011
47797
|
target_project_id: Schema$1.optional(Schema$1.NullOr(Schema$1.Number)),
|
|
@@ -47036,6 +47822,7 @@ function normalizeGitLabMergeRequestRecord(raw) {
|
|
|
47036
47822
|
const targetProjectPath = projectPathWithNamespace(raw.target_project);
|
|
47037
47823
|
const isCrossRepository = typeof raw.source_project_id === "number" && typeof raw.target_project_id === "number" ? raw.source_project_id !== raw.target_project_id : sourceProjectPath !== null && targetProjectPath !== null ? sourceProjectPath.toLowerCase() !== targetProjectPath.toLowerCase() : void 0;
|
|
47038
47824
|
const headRepositoryOwnerLogin = ownerLoginFromPathWithNamespace(sourceProjectPath);
|
|
47825
|
+
const terminalAt = normalizeGitLabMergeRequestState(raw.state) === "merged" ? raw.merged_at ?? null : normalizeGitLabMergeRequestState(raw.state) === "closed" ? raw.closed_at ?? null : null;
|
|
47039
47826
|
return {
|
|
47040
47827
|
number: raw.iid,
|
|
47041
47828
|
title: raw.title,
|
|
@@ -47044,6 +47831,7 @@ function normalizeGitLabMergeRequestRecord(raw) {
|
|
|
47044
47831
|
headRefName: raw.source_branch,
|
|
47045
47832
|
state: normalizeGitLabMergeRequestState(raw.state),
|
|
47046
47833
|
updatedAt: raw.updated_at ?? Option.none(),
|
|
47834
|
+
...terminalAt == null ? {} : { terminalAt },
|
|
47047
47835
|
...typeof isCrossRepository === "boolean" ? { isCrossRepository } : {},
|
|
47048
47836
|
...sourceProjectPath ? { headRepositoryNameWithOwner: sourceProjectPath } : {},
|
|
47049
47837
|
...headRepositoryOwnerLogin ? { headRepositoryOwnerLogin } : {}
|
|
@@ -47052,13 +47840,16 @@ function normalizeGitLabMergeRequestRecord(raw) {
|
|
|
47052
47840
|
const decodeGitLabMergeRequestList = decodeJsonResult(Schema$1.Array(Schema$1.Unknown));
|
|
47053
47841
|
const decodeGitLabMergeRequest = decodeJsonResult(GitLabMergeRequestSchema);
|
|
47054
47842
|
const decodeGitLabMergeRequestEntry = Schema$1.decodeUnknownExit(GitLabMergeRequestSchema);
|
|
47055
|
-
function decodeGitLabMergeRequestListJson(raw) {
|
|
47843
|
+
function decodeGitLabMergeRequestListJson(raw, strict = false) {
|
|
47056
47844
|
const result = decodeGitLabMergeRequestList(raw);
|
|
47057
47845
|
if (Result.isSuccess(result)) {
|
|
47058
47846
|
const mergeRequests = [];
|
|
47059
47847
|
for (const entry of result.success) {
|
|
47060
47848
|
const decodedEntry = decodeGitLabMergeRequestEntry(entry);
|
|
47061
|
-
if (Exit.isFailure(decodedEntry))
|
|
47849
|
+
if (Exit.isFailure(decodedEntry)) {
|
|
47850
|
+
if (strict) return Result.fail(decodedEntry.cause);
|
|
47851
|
+
continue;
|
|
47852
|
+
}
|
|
47062
47853
|
mergeRequests.push(normalizeGitLabMergeRequestRecord(decodedEntry.value));
|
|
47063
47854
|
}
|
|
47064
47855
|
return Result.succeed(mergeRequests);
|
|
@@ -47299,7 +48090,7 @@ function parseRepositoryPath(repository) {
|
|
|
47299
48090
|
projectPath
|
|
47300
48091
|
};
|
|
47301
48092
|
}
|
|
47302
|
-
const make$
|
|
48093
|
+
const make$45 = Effect.gen(function* () {
|
|
47303
48094
|
const process = yield* VcsProcess;
|
|
47304
48095
|
const run = (input, mapError) => process.run({
|
|
47305
48096
|
operation: "GitLabCli.execute",
|
|
@@ -47336,7 +48127,7 @@ const make$44 = Effect.gen(function* () {
|
|
|
47336
48127
|
"--output",
|
|
47337
48128
|
"json"
|
|
47338
48129
|
]
|
|
47339
|
-
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => raw.length === 0 ? Effect.succeed([]) : Effect.sync(() => decodeGitLabMergeRequestListJson(raw)).pipe(Effect.flatMap((decoded) => {
|
|
48130
|
+
}).pipe(Effect.map((result) => result.stdout.trim()), Effect.flatMap((raw) => raw.length === 0 && !input.strict ? Effect.succeed([]) : Effect.sync(() => decodeGitLabMergeRequestListJson(raw, input.strict)).pipe(Effect.flatMap((decoded) => {
|
|
47340
48131
|
if (!Result.isSuccess(decoded)) return Effect.fail(new GitLabMergeRequestListDecodeError({
|
|
47341
48132
|
operation: "listMergeRequests",
|
|
47342
48133
|
command: "glab",
|
|
@@ -47450,7 +48241,7 @@ const make$44 = Effect.gen(function* () {
|
|
|
47450
48241
|
}).pipe(Effect.asVoid)
|
|
47451
48242
|
});
|
|
47452
48243
|
});
|
|
47453
|
-
const layer$33 = Layer.effect(GitLabCli, make$
|
|
48244
|
+
const layer$33 = Layer.effect(GitLabCli, make$45);
|
|
47454
48245
|
//#endregion
|
|
47455
48246
|
//#region src/sourceControl/gitLabAuthStatus.ts
|
|
47456
48247
|
const HOST_LINE_PATTERN = /^(?:[a-z0-9](?:[a-z0-9.-]*[a-z0-9])?|\[[a-f0-9:.]+\])(?::\d+)?$/iu;
|
|
@@ -47497,6 +48288,7 @@ function toChangeRequest$2(summary) {
|
|
|
47497
48288
|
headRefName: summary.headRefName,
|
|
47498
48289
|
state: summary.state ?? "open",
|
|
47499
48290
|
updatedAt: summary.updatedAt ?? Option.none(),
|
|
48291
|
+
...summary.terminalAt == null ? {} : { terminalAt: summary.terminalAt },
|
|
47500
48292
|
...summary.isCrossRepository !== void 0 ? { isCrossRepository: summary.isCrossRepository } : {},
|
|
47501
48293
|
...summary.headRepositoryNameWithOwner !== void 0 ? { headRepositoryNameWithOwner: summary.headRepositoryNameWithOwner } : {},
|
|
47502
48294
|
...summary.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: summary.headRepositoryOwnerLogin } : {}
|
|
@@ -47547,7 +48339,7 @@ const discovery = {
|
|
|
47547
48339
|
refineUnknownRemote: refineUnknownGitLabRemote,
|
|
47548
48340
|
installHint: "Install the GitLab command-line tool (`glab`) from https://gitlab.com/gitlab-org/cli or your package manager (for example `brew install glab`)."
|
|
47549
48341
|
};
|
|
47550
|
-
const make$
|
|
48342
|
+
const make$44 = Effect.gen(function* () {
|
|
47551
48343
|
const gitlab = yield* GitLabCli;
|
|
47552
48344
|
return SourceControlProvider.of({
|
|
47553
48345
|
kind: "gitlab",
|
|
@@ -47558,6 +48350,7 @@ const make$43 = Effect.gen(function* () {
|
|
|
47558
48350
|
headSelector: input.headSelector,
|
|
47559
48351
|
...source ? { source } : {},
|
|
47560
48352
|
state: input.state,
|
|
48353
|
+
...input.strict !== void 0 ? { strict: input.strict } : {},
|
|
47561
48354
|
...input.limit !== void 0 ? { limit: input.limit } : {}
|
|
47562
48355
|
}).pipe(Effect.map((items) => items.map(toChangeRequest$2)), Effect.mapError((error) => new SourceControlProviderError({
|
|
47563
48356
|
provider: "gitlab",
|
|
@@ -47635,7 +48428,7 @@ const make$43 = Effect.gen(function* () {
|
|
|
47635
48428
|
})))
|
|
47636
48429
|
});
|
|
47637
48430
|
});
|
|
47638
|
-
Layer.effect(SourceControlProvider, make$
|
|
48431
|
+
Layer.effect(SourceControlProvider, make$44);
|
|
47639
48432
|
//#endregion
|
|
47640
48433
|
//#region src/sourceControl/SourceControlProviderRegistry.ts
|
|
47641
48434
|
const PROVIDER_DETECTION_CACHE_CAPACITY = 2048;
|
|
@@ -47791,12 +48584,12 @@ const makeWithProviders = Effect.fn("makeSourceControlProviderRegistryWithProvid
|
|
|
47791
48584
|
})), { concurrency: "unbounded" })
|
|
47792
48585
|
});
|
|
47793
48586
|
});
|
|
47794
|
-
const make$
|
|
47795
|
-
const github = yield* make$
|
|
47796
|
-
const gitlab = yield* make$
|
|
47797
|
-
const bitbucket = yield* make$
|
|
48587
|
+
const make$43 = Effect.gen(function* () {
|
|
48588
|
+
const github = yield* make$46;
|
|
48589
|
+
const gitlab = yield* make$44;
|
|
48590
|
+
const bitbucket = yield* make$48;
|
|
47798
48591
|
const bitbucketDiscovery = yield* makeDiscovery;
|
|
47799
|
-
const azureDevOps = yield* make$
|
|
48592
|
+
const azureDevOps = yield* make$50;
|
|
47800
48593
|
return yield* makeWithProviders([
|
|
47801
48594
|
{
|
|
47802
48595
|
kind: "github",
|
|
@@ -47820,7 +48613,7 @@ const make$42 = Effect.gen(function* () {
|
|
|
47820
48613
|
}
|
|
47821
48614
|
]);
|
|
47822
48615
|
});
|
|
47823
|
-
const layer$31 = Layer.effect(SourceControlProviderRegistry, make$
|
|
48616
|
+
const layer$31 = Layer.effect(SourceControlProviderRegistry, make$43);
|
|
47824
48617
|
//#endregion
|
|
47825
48618
|
//#region src/sourceControl/PrTemplateDetection.ts
|
|
47826
48619
|
const TEMPLATE_MAX_BYTES = 8e3;
|
|
@@ -47942,6 +48735,7 @@ const detectPrTemplate = Effect.fn("detectPrTemplate")(function* (cwd, treeish,
|
|
|
47942
48735
|
});
|
|
47943
48736
|
//#endregion
|
|
47944
48737
|
//#region src/git/GitManager.ts
|
|
48738
|
+
const COMPLETION_PR_LIST_LIMIT = 100;
|
|
47945
48739
|
var GitManager = class extends Context.Service()("@p4code/cli/git/GitManager") {};
|
|
47946
48740
|
const COMMIT_TIMEOUT_MS = 10 * 6e4;
|
|
47947
48741
|
const MAX_PROGRESS_TEXT_LENGTH = 500;
|
|
@@ -48190,7 +48984,7 @@ function toPullRequestHeadRemoteInfo(pr) {
|
|
|
48190
48984
|
...pr.headRepositoryOwnerLogin !== void 0 ? { headRepositoryOwnerLogin: pr.headRepositoryOwnerLogin } : {}
|
|
48191
48985
|
};
|
|
48192
48986
|
}
|
|
48193
|
-
const make$
|
|
48987
|
+
const make$42 = Effect.gen(function* () {
|
|
48194
48988
|
const gitCore = yield* GitVcsDriver;
|
|
48195
48989
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
48196
48990
|
const textGeneration = yield* TextGeneration;
|
|
@@ -48568,6 +49362,57 @@ const make$41 = Effect.gen(function* () {
|
|
|
48568
49362
|
if (latestOpenPr) return latestOpenPr;
|
|
48569
49363
|
return parsed[0] ?? null;
|
|
48570
49364
|
});
|
|
49365
|
+
const threadCompletionPrState = Effect.fn("GitManager.threadCompletionPrState")(function* (input) {
|
|
49366
|
+
const details = yield* gitCore.statusDetails(input.cwd);
|
|
49367
|
+
if (!details.isRepo) return { state: "none" };
|
|
49368
|
+
if (!details.hasOriginRemote) {
|
|
49369
|
+
const remotes = yield* gitCore.execute({
|
|
49370
|
+
operation: "GitManager.threadCompletionPrState.remotes",
|
|
49371
|
+
cwd: input.cwd,
|
|
49372
|
+
args: ["remote"]
|
|
49373
|
+
});
|
|
49374
|
+
if (remotes.stdoutTruncated) return { state: "unknown" };
|
|
49375
|
+
if (remotes.stdout.trim().length === 0) return { state: "none" };
|
|
49376
|
+
}
|
|
49377
|
+
if (details.branch === null || input.branch !== null && details.branch !== input.branch) return { state: "unknown" };
|
|
49378
|
+
const context = yield* resolveBranchHeadContext(input.cwd, {
|
|
49379
|
+
branch: details.branch,
|
|
49380
|
+
upstreamRef: details.upstreamRef
|
|
49381
|
+
});
|
|
49382
|
+
const provider = yield* sourceControlProvider(input.cwd);
|
|
49383
|
+
if (context.headSelectors.length === 0) return { state: "unknown" };
|
|
49384
|
+
const terminalTimes = [];
|
|
49385
|
+
for (const headSelector of context.headSelectors) {
|
|
49386
|
+
const open = yield* provider.listChangeRequests({
|
|
49387
|
+
cwd: input.cwd,
|
|
49388
|
+
headSelector,
|
|
49389
|
+
state: "open",
|
|
49390
|
+
limit: COMPLETION_PR_LIST_LIMIT,
|
|
49391
|
+
strict: true
|
|
49392
|
+
});
|
|
49393
|
+
if (open.some((pr) => matchesBranchHeadContext(toPullRequestInfo(pr), context))) return { state: "open" };
|
|
49394
|
+
if (open.length > 0) return { state: "unknown" };
|
|
49395
|
+
const history = yield* provider.listChangeRequests({
|
|
49396
|
+
cwd: input.cwd,
|
|
49397
|
+
headSelector,
|
|
49398
|
+
state: "all",
|
|
49399
|
+
limit: COMPLETION_PR_LIST_LIMIT,
|
|
49400
|
+
strict: true
|
|
49401
|
+
});
|
|
49402
|
+
if (history.length >= COMPLETION_PR_LIST_LIMIT) return { state: "unknown" };
|
|
49403
|
+
for (const pr of history) {
|
|
49404
|
+
if (!matchesBranchHeadContext(toPullRequestInfo(pr), context)) return { state: "unknown" };
|
|
49405
|
+
if (pr.state === "open") return { state: "open" };
|
|
49406
|
+
if (pr.terminalAt == null || !Number.isFinite(Date.parse(pr.terminalAt))) return { state: "unknown" };
|
|
49407
|
+
terminalTimes.push(DateTime.formatIso(DateTime.makeUnsafe(pr.terminalAt)));
|
|
49408
|
+
}
|
|
49409
|
+
}
|
|
49410
|
+
const terminalAt = terminalTimes.toSorted().at(-1);
|
|
49411
|
+
return terminalAt === void 0 ? { state: "none" } : {
|
|
49412
|
+
state: "terminal",
|
|
49413
|
+
terminalAt
|
|
49414
|
+
};
|
|
49415
|
+
});
|
|
48571
49416
|
const buildCompletionToast = Effect.fn("buildCompletionToast")(function* (cwd, result) {
|
|
48572
49417
|
const terms = yield* sourceControlProvider(cwd).pipe(Effect.map((provider) => getChangeRequestTerminologyForKind(provider.kind)), Effect.orElseSucceed(() => getChangeRequestTerminologyForKind("unknown")));
|
|
48573
49418
|
const summary = summarizeGitActionResult(result, terms);
|
|
@@ -49101,6 +49946,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
49101
49946
|
}))));
|
|
49102
49947
|
});
|
|
49103
49948
|
return GitManager.of({
|
|
49949
|
+
threadCompletionPrState,
|
|
49104
49950
|
localStatus,
|
|
49105
49951
|
remoteStatus,
|
|
49106
49952
|
status,
|
|
@@ -49112,7 +49958,7 @@ const make$41 = Effect.gen(function* () {
|
|
|
49112
49958
|
runStackedAction
|
|
49113
49959
|
});
|
|
49114
49960
|
});
|
|
49115
|
-
const layer$30 = Layer.effect(GitManager, make$
|
|
49961
|
+
const layer$30 = Layer.effect(GitManager, make$42);
|
|
49116
49962
|
//#endregion
|
|
49117
49963
|
//#region src/git/GitWorkflowService.ts
|
|
49118
49964
|
var GitWorkflowService = class extends Context.Service()("@p4code/cli/git/GitWorkflowService") {};
|
|
@@ -49149,7 +49995,7 @@ function nonRepositoryListRefs() {
|
|
|
49149
49995
|
totalCount: 0
|
|
49150
49996
|
};
|
|
49151
49997
|
}
|
|
49152
|
-
const make$
|
|
49998
|
+
const make$41 = Effect.gen(function* () {
|
|
49153
49999
|
const registry = yield* VcsDriverRegistry;
|
|
49154
50000
|
const git = yield* GitVcsDriver;
|
|
49155
50001
|
const gitManager = yield* GitManager;
|
|
@@ -49235,7 +50081,7 @@ const make$40 = Effect.gen(function* () {
|
|
|
49235
50081
|
renameBranch: (input) => ensureGit("GitWorkflowService.renameBranch", input.cwd).pipe(Effect.andThen(git.renameBranch(input)))
|
|
49236
50082
|
});
|
|
49237
50083
|
});
|
|
49238
|
-
const layer$29 = Layer.effect(GitWorkflowService, make$
|
|
50084
|
+
const layer$29 = Layer.effect(GitWorkflowService, make$41);
|
|
49239
50085
|
//#endregion
|
|
49240
50086
|
//#region src/pullRequest/PullRequestProvider.ts
|
|
49241
50087
|
/**
|
|
@@ -49596,7 +50442,7 @@ function isReviewerName(value) {
|
|
|
49596
50442
|
const name = value.trim();
|
|
49597
50443
|
return name.length > 0 && !name.startsWith("-");
|
|
49598
50444
|
}
|
|
49599
|
-
const make$
|
|
50445
|
+
const make$40 = Effect.gen(function* () {
|
|
49600
50446
|
const azure = yield* AzureDevOpsCli;
|
|
49601
50447
|
const detectArgs = ["--detect", "true"];
|
|
49602
50448
|
const executeJson = (input) => azure.execute({
|
|
@@ -49796,7 +50642,7 @@ const make$39 = Effect.gen(function* () {
|
|
|
49796
50642
|
}).pipe(Effect.asVoid)
|
|
49797
50643
|
});
|
|
49798
50644
|
});
|
|
49799
|
-
const layer$28 = Layer.effect(AzureDevOpsPullRequestCli, make$
|
|
50645
|
+
const layer$28 = Layer.effect(AzureDevOpsPullRequestCli, make$40);
|
|
49800
50646
|
//#endregion
|
|
49801
50647
|
//#region src/pullRequest/AzureDevOpsPullRequestProvider.ts
|
|
49802
50648
|
const CAPABILITIES$3 = {
|
|
@@ -49871,7 +50717,7 @@ function toChangeRequest$1(pullRequest) {
|
|
|
49871
50717
|
labels: []
|
|
49872
50718
|
};
|
|
49873
50719
|
}
|
|
49874
|
-
const make$
|
|
50720
|
+
const make$39 = Effect.gen(function* () {
|
|
49875
50721
|
const cli = yield* AzureDevOpsPullRequestCli;
|
|
49876
50722
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
49877
50723
|
provider: "azure-devops",
|
|
@@ -50611,7 +51457,7 @@ function mergeStrategy(method) {
|
|
|
50611
51457
|
default: return "merge_commit";
|
|
50612
51458
|
}
|
|
50613
51459
|
}
|
|
50614
|
-
const make$
|
|
51460
|
+
const make$38 = Effect.gen(function* () {
|
|
50615
51461
|
const bitbucket = yield* BitbucketApi;
|
|
50616
51462
|
/**
|
|
50617
51463
|
* The repository's own path, and the workspace above it — which the people who may review are
|
|
@@ -50891,7 +51737,7 @@ const make$37 = Effect.gen(function* () {
|
|
|
50891
51737
|
}).pipe(Effect.asVoid))
|
|
50892
51738
|
});
|
|
50893
51739
|
});
|
|
50894
|
-
const layer$27 = Layer.effect(BitbucketPullRequestApi, make$
|
|
51740
|
+
const layer$27 = Layer.effect(BitbucketPullRequestApi, make$38);
|
|
50895
51741
|
//#endregion
|
|
50896
51742
|
//#region src/pullRequest/BitbucketPullRequestProvider.ts
|
|
50897
51743
|
const CAPABILITIES$2 = {
|
|
@@ -50971,7 +51817,7 @@ function toChangeRequest(pullRequest) {
|
|
|
50971
51817
|
labels: []
|
|
50972
51818
|
};
|
|
50973
51819
|
}
|
|
50974
|
-
const make$
|
|
51820
|
+
const make$37 = Effect.gen(function* () {
|
|
50975
51821
|
const api = yield* BitbucketPullRequestApi;
|
|
50976
51822
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
50977
51823
|
provider: "bitbucket",
|
|
@@ -52858,7 +53704,7 @@ function actionArgs$1(action, mergeMethod, updateMethod) {
|
|
|
52858
53704
|
case "reopen": return ["reopen"];
|
|
52859
53705
|
}
|
|
52860
53706
|
}
|
|
52861
|
-
const make$
|
|
53707
|
+
const make$36 = Effect.gen(function* () {
|
|
52862
53708
|
const github = yield* GitHubCli;
|
|
52863
53709
|
/**
|
|
52864
53710
|
* The pull request's own node id, which is what a mutation against the pull request itself is
|
|
@@ -53578,7 +54424,7 @@ const make$35 = Effect.gen(function* () {
|
|
|
53578
54424
|
})))
|
|
53579
54425
|
});
|
|
53580
54426
|
});
|
|
53581
|
-
const layer$26 = Layer.effect(GitHubPullRequestCli, make$
|
|
54427
|
+
const layer$26 = Layer.effect(GitHubPullRequestCli, make$36);
|
|
53582
54428
|
//#endregion
|
|
53583
54429
|
//#region src/pullRequest/GitHubPullRequestProvider.ts
|
|
53584
54430
|
const CAPABILITIES$1 = {
|
|
@@ -53693,7 +54539,7 @@ function loginAvatarUrl(login, host) {
|
|
|
53693
54539
|
}
|
|
53694
54540
|
/** True where markdown would render nothing: whitespace, or only HTML comments. */
|
|
53695
54541
|
const rendersEmpty = (body) => body.replace(/<!--[\s\S]*?-->/g, "").trim().length === 0;
|
|
53696
|
-
const make$
|
|
54542
|
+
const make$35 = Effect.gen(function* () {
|
|
53697
54543
|
const cli = yield* GitHubPullRequestCli;
|
|
53698
54544
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
53699
54545
|
provider: "github",
|
|
@@ -54712,7 +55558,7 @@ function actionArgs(action, mergeMethod) {
|
|
|
54712
55558
|
case "reopen": return ["reopen"];
|
|
54713
55559
|
}
|
|
54714
55560
|
}
|
|
54715
|
-
const make$
|
|
55561
|
+
const make$34 = Effect.gen(function* () {
|
|
54716
55562
|
const gitlab = yield* GitLabCli;
|
|
54717
55563
|
const api = (input) => gitlab.execute({
|
|
54718
55564
|
cwd: input.cwd,
|
|
@@ -55283,7 +56129,7 @@ const make$33 = Effect.gen(function* () {
|
|
|
55283
56129
|
}).pipe(Effect.asVoid)
|
|
55284
56130
|
});
|
|
55285
56131
|
});
|
|
55286
|
-
const layer$25 = Layer.effect(GitLabPullRequestCli, make$
|
|
56132
|
+
const layer$25 = Layer.effect(GitLabPullRequestCli, make$34);
|
|
55287
56133
|
//#endregion
|
|
55288
56134
|
//#region src/pullRequest/GitLabPullRequestProvider.ts
|
|
55289
56135
|
const CAPABILITIES = {
|
|
@@ -55363,7 +56209,7 @@ function reasonFor(error) {
|
|
|
55363
56209
|
if (error._tag === "GitLabCliAuthenticationError") return "unauthenticated";
|
|
55364
56210
|
return "failed";
|
|
55365
56211
|
}
|
|
55366
|
-
const make$
|
|
56212
|
+
const make$33 = Effect.gen(function* () {
|
|
55367
56213
|
const cli = yield* GitLabPullRequestCli;
|
|
55368
56214
|
const fail = (operation) => (error) => new PullRequestProviderError({
|
|
55369
56215
|
provider: "gitlab",
|
|
@@ -55506,13 +56352,13 @@ function fromProviders(providers) {
|
|
|
55506
56352
|
* The hosts this build can read change requests from. A host with no entry here still shows up
|
|
55507
56353
|
* in the provider list as unimplemented, so its projects are explained rather than missing.
|
|
55508
56354
|
*/
|
|
55509
|
-
const make$
|
|
55510
|
-
make$
|
|
55511
|
-
make$
|
|
55512
|
-
make$
|
|
55513
|
-
make$
|
|
56355
|
+
const make$32 = Effect.map(Effect.all([
|
|
56356
|
+
make$35,
|
|
56357
|
+
make$33,
|
|
56358
|
+
make$37,
|
|
56359
|
+
make$39
|
|
55514
56360
|
]), fromProviders);
|
|
55515
|
-
const layer$24 = Layer.effect(PullRequestProviderRegistry, make$
|
|
56361
|
+
const layer$24 = Layer.effect(PullRequestProviderRegistry, make$32).pipe(Layer.provide(layer$26.pipe(Layer.provide(layer$35))), Layer.provide(layer$25.pipe(Layer.provide(layer$33))), Layer.provide(layer$27.pipe(Layer.provide(layer$37))), Layer.provide(layer$28.pipe(Layer.provide(layer$39))));
|
|
55516
56362
|
//#endregion
|
|
55517
56363
|
//#region src/pullRequest/PullRequestService.ts
|
|
55518
56364
|
/**
|
|
@@ -55700,7 +56546,7 @@ function repositoryIdentityOf(project) {
|
|
|
55700
56546
|
if (identity.displayName) return identity.displayName;
|
|
55701
56547
|
return identity.owner && identity.name ? `${identity.owner}/${identity.name}` : null;
|
|
55702
56548
|
}
|
|
55703
|
-
const make$
|
|
56549
|
+
const make$31 = Effect.gen(function* () {
|
|
55704
56550
|
const registry = yield* PullRequestProviderRegistry;
|
|
55705
56551
|
const projections = yield* ProjectionSnapshotQuery;
|
|
55706
56552
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
@@ -56670,7 +57516,7 @@ const make$30 = Effect.gen(function* () {
|
|
|
56670
57516
|
invalidate
|
|
56671
57517
|
});
|
|
56672
57518
|
});
|
|
56673
|
-
const layer$23 = Layer.effect(PullRequestService, make$
|
|
57519
|
+
const layer$23 = Layer.effect(PullRequestService, make$31);
|
|
56674
57520
|
//#endregion
|
|
56675
57521
|
//#region src/orchestration/ThreadWorkspaceLifecycle.ts
|
|
56676
57522
|
var ThreadWorkspaceLifecycleError = class extends Data.TaggedError("ThreadWorkspaceLifecycleError") {};
|
|
@@ -56714,7 +57560,7 @@ const mapLifecycleError = Effect.mapError((cause) => cause instanceof ThreadWork
|
|
|
56714
57560
|
detail: "Thread workspace lifecycle operation failed.",
|
|
56715
57561
|
cause
|
|
56716
57562
|
}));
|
|
56717
|
-
const make$
|
|
57563
|
+
const make$30 = Effect.gen(function* () {
|
|
56718
57564
|
const snapshots = yield* ProjectionSnapshotQuery;
|
|
56719
57565
|
const engine = yield* OrchestrationEngineService;
|
|
56720
57566
|
const gitWorkflow = yield* GitWorkflowService;
|
|
@@ -56968,7 +57814,7 @@ const make$29 = Effect.gen(function* () {
|
|
|
56968
57814
|
record
|
|
56969
57815
|
};
|
|
56970
57816
|
});
|
|
56971
|
-
const layer$22 = Layer.effect(ThreadWorkspaceLifecycleService, make$
|
|
57817
|
+
const layer$22 = Layer.effect(ThreadWorkspaceLifecycleService, make$30);
|
|
56972
57818
|
//#endregion
|
|
56973
57819
|
//#region src/textGeneration/BtwRequestCoordinator.ts
|
|
56974
57820
|
const MAX_PENDING_BTW_CANCELLATIONS = 256;
|
|
@@ -59512,7 +60358,7 @@ function makeUpdateState(input) {
|
|
|
59512
60358
|
output: input.output ?? null
|
|
59513
60359
|
};
|
|
59514
60360
|
}
|
|
59515
|
-
const make$
|
|
60361
|
+
const make$29 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
59516
60362
|
const providerRegistry = yield* ProviderRegistry;
|
|
59517
60363
|
const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
|
|
59518
60364
|
const httpClient = yield* HttpClient.HttpClient;
|
|
@@ -59627,7 +60473,7 @@ const make$28 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
|
|
|
59627
60473
|
});
|
|
59628
60474
|
return ProviderMaintenanceRunner.of({ updateProvider });
|
|
59629
60475
|
});
|
|
59630
|
-
const layer$21 = Layer.effect(ProviderMaintenanceRunner, make$
|
|
60476
|
+
const layer$21 = Layer.effect(ProviderMaintenanceRunner, make$29());
|
|
59631
60477
|
//#endregion
|
|
59632
60478
|
//#region src/provider/Drivers/ClaudeHome.ts
|
|
59633
60479
|
const resolveClaudeHomePath = Effect.fn("resolveClaudeHomePath")(function* (config) {
|
|
@@ -60737,7 +61583,7 @@ Layer.succeed(UsageService, UsageService.of({ readSummary: (input) => Effect.suc
|
|
|
60737
61583
|
},
|
|
60738
61584
|
scanDurationMs: 0
|
|
60739
61585
|
}) }));
|
|
60740
|
-
const make$
|
|
61586
|
+
const make$28 = Effect.gen(function* () {
|
|
60741
61587
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
60742
61588
|
const path = yield* Path.Path;
|
|
60743
61589
|
const config = yield* ServerConfig$1;
|
|
@@ -60975,7 +61821,7 @@ const make$27 = Effect.gen(function* () {
|
|
|
60975
61821
|
};
|
|
60976
61822
|
}) };
|
|
60977
61823
|
});
|
|
60978
|
-
const layer$20 = Layer.effect(UsageService, make$
|
|
61824
|
+
const layer$20 = Layer.effect(UsageService, make$28);
|
|
60979
61825
|
//#endregion
|
|
60980
61826
|
//#region src/feed/FeedStore.ts
|
|
60981
61827
|
const storageFailure = (message) => new FeedError({
|
|
@@ -61339,7 +62185,7 @@ const jsonRequest = Effect.fn("FeedService.jsonRequest")(function* (url, token,
|
|
|
61339
62185
|
catch: () => fail("hub_unavailable", "Hub returned invalid JSON.")
|
|
61340
62186
|
});
|
|
61341
62187
|
});
|
|
61342
|
-
const make$
|
|
62188
|
+
const make$27 = Effect.gen(function* () {
|
|
61343
62189
|
const hubLink = yield* HubLink;
|
|
61344
62190
|
const providers = yield* ProviderInstanceRegistry;
|
|
61345
62191
|
const config = yield* ServerConfig$1;
|
|
@@ -61577,7 +62423,7 @@ var FeedService = class extends Context.Reference("@p4code/cli/feed/FeedService"
|
|
|
61577
62423
|
markRead: unavailable,
|
|
61578
62424
|
cleanup: unavailable
|
|
61579
62425
|
}) }) {};
|
|
61580
|
-
const layer$19 = Layer.effect(FeedService, make$
|
|
62426
|
+
const layer$19 = Layer.effect(FeedService, make$27);
|
|
61581
62427
|
const SKILL_MANIFEST_FILENAME = "SKILL.md";
|
|
61582
62428
|
/**
|
|
61583
62429
|
* Split a catalogue id (`owner/repo/skill-name`) into its parts.
|
|
@@ -61723,7 +62569,7 @@ const emptyFetch = (id, unavailable) => ({
|
|
|
61723
62569
|
skipped: [],
|
|
61724
62570
|
unavailable
|
|
61725
62571
|
});
|
|
61726
|
-
const make$
|
|
62572
|
+
const make$26 = Effect.gen(function* () {
|
|
61727
62573
|
const http = yield* HttpClient.HttpClient;
|
|
61728
62574
|
const request = Effect.fn("SkillRegistry.request")(function* (url) {
|
|
61729
62575
|
return yield* http.execute(HttpClientRequest.get(url).pipe(HttpClientRequest.setHeader("accept", "application/json"), HttpClientRequest.setHeader("user-agent", "p4code"))).pipe(Effect.timeout(REQUEST_TIMEOUT_MS));
|
|
@@ -61794,7 +62640,7 @@ const make$25 = Effect.gen(function* () {
|
|
|
61794
62640
|
fetch
|
|
61795
62641
|
};
|
|
61796
62642
|
});
|
|
61797
|
-
const layer$18 = Layer.effect(SkillRegistry, make$
|
|
62643
|
+
const layer$18 = Layer.effect(SkillRegistry, make$26);
|
|
61798
62644
|
//#endregion
|
|
61799
62645
|
//#region src/mcp/McpInvocationContext.ts
|
|
61800
62646
|
var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
|
|
@@ -61897,9 +62743,9 @@ const requireThreadControlTarget = Effect.fn("mcp.requireThreadControlTarget")(f
|
|
|
61897
62743
|
* The guard on starting a thread, which is a different question from acting on
|
|
61898
62744
|
* one: it is not "which thread" but "may this session make more of them".
|
|
61899
62745
|
*/
|
|
61900
|
-
const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* () {
|
|
62746
|
+
const requireThreadSpawn = Effect.fn("mcp.requireThreadSpawn")(function* (fusion = false) {
|
|
61901
62747
|
const invocation = yield* requireThreadCapability();
|
|
61902
|
-
if (invocation.mayCreateThreads !== true) return yield* new ThreadSpawnNotPermittedError({
|
|
62748
|
+
if (invocation.mayCreateThreads !== true && !(fusion && invocation.mayCreateFusionPairs === true)) return yield* new ThreadSpawnNotPermittedError({
|
|
61903
62749
|
threadId: invocation.threadId,
|
|
61904
62750
|
detail: "this thread was itself started by an agent, and spawning goes one level deep so a runaway loop has a bound"
|
|
61905
62751
|
});
|
|
@@ -62022,7 +62868,7 @@ const classifyResponseError = (context, error) => {
|
|
|
62022
62868
|
});
|
|
62023
62869
|
}
|
|
62024
62870
|
};
|
|
62025
|
-
const make$
|
|
62871
|
+
const make$25 = Effect.gen(function* PreviewAutomationBrokerMake() {
|
|
62026
62872
|
const crypto = yield* Crypto.Crypto;
|
|
62027
62873
|
const state = yield* SynchronizedRef.make({
|
|
62028
62874
|
clients: /* @__PURE__ */ new Map(),
|
|
@@ -62256,7 +63102,7 @@ const make$24 = Effect.gen(function* PreviewAutomationBrokerMake() {
|
|
|
62256
63102
|
invoke
|
|
62257
63103
|
});
|
|
62258
63104
|
}).pipe(Effect.withSpan("PreviewAutomationBroker.make"));
|
|
62259
|
-
const layer$17 = Layer.effect(PreviewAutomationBroker, make$
|
|
63105
|
+
const layer$17 = Layer.effect(PreviewAutomationBroker, make$25);
|
|
62260
63106
|
//#endregion
|
|
62261
63107
|
//#region src/preview/Manager.ts
|
|
62262
63108
|
/**
|
|
@@ -62320,7 +63166,7 @@ const buildIdleSnapshot = (input) => ({
|
|
|
62320
63166
|
viewport: FILL_PREVIEW_VIEWPORT,
|
|
62321
63167
|
updatedAt: input.updatedAt
|
|
62322
63168
|
});
|
|
62323
|
-
const make$
|
|
63169
|
+
const make$24 = Effect.gen(function* PreviewManagerMake() {
|
|
62324
63170
|
const serverEpoch = NodeCrypto.randomUUID();
|
|
62325
63171
|
const stateRef = yield* SynchronizedRef.make(initialState);
|
|
62326
63172
|
const eventsPubSub = yield* PubSub.unbounded();
|
|
@@ -62551,12 +63397,15 @@ const make$23 = Effect.gen(function* PreviewManagerMake() {
|
|
|
62551
63397
|
subscribeEvents: PubSub.subscribe(eventsPubSub)
|
|
62552
63398
|
});
|
|
62553
63399
|
}).pipe(Effect.withSpan("PreviewManager.make"));
|
|
62554
|
-
const layer$16 = Layer.effect(PreviewManager, make$
|
|
63400
|
+
const layer$16 = Layer.effect(PreviewManager, make$24);
|
|
62555
63401
|
//#endregion
|
|
62556
63402
|
//#region src/workspace/WorkspaceSearchIndex.ts
|
|
62557
63403
|
const WORKSPACE_INDEX_MAX_ENTRIES = 25e3;
|
|
62558
63404
|
const WORKSPACE_INDEX_PAGE_SIZE = 25002;
|
|
62559
63405
|
const WORKSPACE_INDEX_SCAN_TIMEOUT = "15 seconds";
|
|
63406
|
+
const CONTENT_SEARCH_TIME_BUDGET_MS = 250;
|
|
63407
|
+
const CONTENT_SEARCH_MAX_MATCHES_PER_FILE = 100;
|
|
63408
|
+
const CONTENT_INDEX_READY_TIMEOUT_MS = 15e3;
|
|
62560
63409
|
const WORKSPACE_INDEX_IDLE_TTL = "15 minutes";
|
|
62561
63410
|
const WORKSPACE_INDEX_SCAN_POLL_INTERVAL = "50 millis";
|
|
62562
63411
|
var WorkspaceSearchIndexCreateFailed = class extends Schema$1.TaggedErrorClass()("WorkspaceSearchIndexCreateFailed", {
|
|
@@ -62650,12 +63499,12 @@ function withDirectoryAncestors(entries) {
|
|
|
62650
63499
|
}
|
|
62651
63500
|
return [...entryByPath.values()];
|
|
62652
63501
|
}
|
|
62653
|
-
const createFinder = Effect.fn("WorkspaceSearchIndex.createFinder")(function* (cwd) {
|
|
63502
|
+
const createFinder = Effect.fn("WorkspaceSearchIndex.createFinder")(function* (cwd, contentSearch) {
|
|
62654
63503
|
const result = yield* Effect.try({
|
|
62655
63504
|
try: () => FileFinder.create({
|
|
62656
63505
|
basePath: cwd,
|
|
62657
63506
|
disableMmapCache: true,
|
|
62658
|
-
disableContentIndexing:
|
|
63507
|
+
disableContentIndexing: !contentSearch,
|
|
62659
63508
|
aiMode: false,
|
|
62660
63509
|
enableFsRootScanning: true,
|
|
62661
63510
|
enableHomeDirScanning: true
|
|
@@ -62685,8 +63534,8 @@ const waitForScan = (cwd, finder, onFailure) => Effect.try({
|
|
|
62685
63534
|
timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
|
|
62686
63535
|
})
|
|
62687
63536
|
}), Effect.withSpan("WorkspaceSearchIndex.waitForScan"));
|
|
62688
|
-
const make$
|
|
62689
|
-
const finder = yield* Effect.acquireRelease(createFinder(cwd), (finder) => Effect.try({
|
|
63537
|
+
const make$23 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd, contentSearch = false) {
|
|
63538
|
+
const finder = yield* Effect.acquireRelease(createFinder(cwd, contentSearch), (finder) => Effect.try({
|
|
62690
63539
|
try: () => finder.destroy(),
|
|
62691
63540
|
catch: (cause) => new WorkspaceSearchIndexDestroyFailed({
|
|
62692
63541
|
cwd,
|
|
@@ -62698,6 +63547,24 @@ const make$22 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
|
|
|
62698
63547
|
reason: "FileFinder.isScanning threw while creating the index.",
|
|
62699
63548
|
cause
|
|
62700
63549
|
}));
|
|
63550
|
+
if (contentSearch) {
|
|
63551
|
+
const ready = yield* Effect.tryPromise({
|
|
63552
|
+
try: () => finder.waitForIndexReady(CONTENT_INDEX_READY_TIMEOUT_MS),
|
|
63553
|
+
catch: (cause) => new WorkspaceSearchIndexCreateFailed({
|
|
63554
|
+
cwd,
|
|
63555
|
+
reason: "Content index initialization failed.",
|
|
63556
|
+
cause
|
|
63557
|
+
})
|
|
63558
|
+
});
|
|
63559
|
+
if (!ready.ok) return yield* new WorkspaceSearchIndexCreateFailed({
|
|
63560
|
+
cwd,
|
|
63561
|
+
reason: ready.error
|
|
63562
|
+
});
|
|
63563
|
+
if (!ready.value) return yield* new WorkspaceSearchIndexScanTimedOut({
|
|
63564
|
+
cwd,
|
|
63565
|
+
timeout: WORKSPACE_INDEX_SCAN_TIMEOUT
|
|
63566
|
+
});
|
|
63567
|
+
}
|
|
62701
63568
|
const runMixedSearch = Effect.fn("WorkspaceSearchIndex.runMixedSearch")(function* (query, pageSize) {
|
|
62702
63569
|
const result = yield* Effect.try({
|
|
62703
63570
|
try: () => finder.mixedSearch(query, { pageSize }),
|
|
@@ -62748,10 +63615,58 @@ const make$22 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
|
|
|
62748
63615
|
const search = Effect.fn("WorkspaceSearchIndex.search")(function* (query, limit) {
|
|
62749
63616
|
return mapMixedSearchResult(yield* runMixedSearch(query, Math.max(1, limit + 1)), limit);
|
|
62750
63617
|
});
|
|
63618
|
+
const searchContents = Effect.fn("WorkspaceSearchIndex.searchContents")(function* (input) {
|
|
63619
|
+
const deadline = performance.now() + CONTENT_SEARCH_TIME_BUDGET_MS;
|
|
63620
|
+
const matches = [];
|
|
63621
|
+
let cursor = null;
|
|
63622
|
+
do {
|
|
63623
|
+
const result = yield* Effect.try({
|
|
63624
|
+
try: () => finder.grep(input.query, {
|
|
63625
|
+
mode: "plain",
|
|
63626
|
+
smartCase: true,
|
|
63627
|
+
maxMatchesPerFile: Math.min(CONTENT_SEARCH_MAX_MATCHES_PER_FILE, input.limit),
|
|
63628
|
+
pageSize: input.limit - matches.length,
|
|
63629
|
+
timeBudgetMs: Math.max(1, Math.ceil(deadline - performance.now())),
|
|
63630
|
+
cursor
|
|
63631
|
+
}),
|
|
63632
|
+
catch: (cause) => new WorkspaceSearchIndexSearchFailed({
|
|
63633
|
+
cwd,
|
|
63634
|
+
queryLength: input.query.length,
|
|
63635
|
+
pageSize: input.limit,
|
|
63636
|
+
reason: "Content search failed.",
|
|
63637
|
+
cause
|
|
63638
|
+
})
|
|
63639
|
+
});
|
|
63640
|
+
if (!result.ok) return yield* new WorkspaceSearchIndexSearchFailed({
|
|
63641
|
+
cwd,
|
|
63642
|
+
queryLength: input.query.length,
|
|
63643
|
+
pageSize: input.limit,
|
|
63644
|
+
reason: result.error
|
|
63645
|
+
});
|
|
63646
|
+
for (const match of result.value.items) {
|
|
63647
|
+
const bytes = Buffer.from(match.lineContent);
|
|
63648
|
+
matches.push({
|
|
63649
|
+
path: toPosixPath(match.relativePath),
|
|
63650
|
+
lineNumber: match.lineNumber,
|
|
63651
|
+
lineContent: match.lineContent,
|
|
63652
|
+
matchRanges: match.matchRanges.map(([start, end]) => ({
|
|
63653
|
+
start: bytes.subarray(0, start).toString().length,
|
|
63654
|
+
end: bytes.subarray(0, end).toString().length
|
|
63655
|
+
}))
|
|
63656
|
+
});
|
|
63657
|
+
}
|
|
63658
|
+
cursor = result.value.nextCursor;
|
|
63659
|
+
} while (matches.length < input.limit && cursor !== null && performance.now() < deadline);
|
|
63660
|
+
return {
|
|
63661
|
+
matches: matches.slice(0, input.limit),
|
|
63662
|
+
truncated: matches.length > input.limit || cursor !== null
|
|
63663
|
+
};
|
|
63664
|
+
});
|
|
62751
63665
|
return WorkspaceSearchIndex.of({
|
|
62752
63666
|
list,
|
|
62753
63667
|
refresh,
|
|
62754
|
-
search
|
|
63668
|
+
search,
|
|
63669
|
+
searchContents
|
|
62755
63670
|
});
|
|
62756
63671
|
});
|
|
62757
63672
|
/**
|
|
@@ -62759,11 +63674,16 @@ const make$22 = Effect.fn("WorkspaceSearchIndex.make")(function* (cwd) {
|
|
|
62759
63674
|
* workspace root. WorkspaceSearchIndexMap owns memoization and idle cleanup;
|
|
62760
63675
|
* using a default cwd here would mix resources from different workspaces.
|
|
62761
63676
|
*/
|
|
62762
|
-
const layer$15 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$
|
|
63677
|
+
const layer$15 = (cwd) => Layer.effect(WorkspaceSearchIndex, make$23(cwd));
|
|
62763
63678
|
var WorkspaceSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceSearchIndexMap", {
|
|
62764
63679
|
lookup: layer$15,
|
|
62765
63680
|
idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
|
|
62766
63681
|
}) {};
|
|
63682
|
+
/** Content indexing is allocated only when workspace content search is used. */
|
|
63683
|
+
var WorkspaceContentSearchIndexMap = class extends LayerMap.Service()("@p4code/cli/workspace/WorkspaceContentSearchIndexMap", {
|
|
63684
|
+
lookup: (cwd) => Layer.effect(WorkspaceSearchIndex, make$23(cwd, true)),
|
|
63685
|
+
idleTimeToLive: WORKSPACE_INDEX_IDLE_TTL
|
|
63686
|
+
}) {};
|
|
62767
63687
|
//#endregion
|
|
62768
63688
|
//#region src/workspace/WorkspaceEntries.ts
|
|
62769
63689
|
var WorkspaceEntriesWindowsPathUnsupportedError = class extends Schema$1.TaggedErrorClass()("WorkspaceEntriesWindowsPathUnsupportedError", {
|
|
@@ -62823,9 +63743,10 @@ const resolveBrowseTarget = Effect.fn("WorkspaceEntries.resolveBrowseTarget")(fu
|
|
|
62823
63743
|
if (!input.cwd) return yield* new WorkspaceEntriesCurrentProjectRequiredError({ partialPath: input.partialPath });
|
|
62824
63744
|
return path.resolve(expandHomePath$1(input.cwd, path), input.partialPath);
|
|
62825
63745
|
});
|
|
62826
|
-
const make$
|
|
63746
|
+
const make$22 = Effect.gen(function* () {
|
|
62827
63747
|
const path = yield* Path.Path;
|
|
62828
63748
|
const workspacePaths = yield* WorkspacePaths;
|
|
63749
|
+
const contentSearchIndexes = yield* WorkspaceContentSearchIndexMap;
|
|
62829
63750
|
const workspaceSearchIndexes = yield* WorkspaceSearchIndexMap;
|
|
62830
63751
|
const normalizeWorkspaceRoot = Effect.fn("WorkspaceEntries.normalizeWorkspaceRoot")(function* (cwd) {
|
|
62831
63752
|
return yield* workspacePaths.normalizeWorkspaceRoot(cwd);
|
|
@@ -62890,14 +63811,21 @@ const make$21 = Effect.gen(function* () {
|
|
|
62890
63811
|
return yield* (yield* WorkspaceSearchIndex).list();
|
|
62891
63812
|
}).pipe(Effect.provide(workspaceSearchIndexes.get(normalizedCwd)));
|
|
62892
63813
|
});
|
|
63814
|
+
const searchContents = Effect.fn("WorkspaceEntries.searchContents")(function* (input) {
|
|
63815
|
+
const cwd = yield* normalizeWorkspaceRoot(input.cwd);
|
|
63816
|
+
return yield* Effect.gen(function* () {
|
|
63817
|
+
return yield* (yield* WorkspaceSearchIndex).searchContents(input);
|
|
63818
|
+
}).pipe(Effect.provide(contentSearchIndexes.get(cwd)));
|
|
63819
|
+
});
|
|
62893
63820
|
return WorkspaceEntries.of({
|
|
62894
63821
|
browse,
|
|
62895
63822
|
list,
|
|
62896
63823
|
refresh,
|
|
62897
|
-
search
|
|
63824
|
+
search,
|
|
63825
|
+
searchContents
|
|
62898
63826
|
});
|
|
62899
63827
|
});
|
|
62900
|
-
const layer$14 = Layer.effect(WorkspaceEntries, make$
|
|
63828
|
+
const layer$14 = Layer.effect(WorkspaceEntries, make$22).pipe(Layer.provide(WorkspaceSearchIndexMap.layer), Layer.provide(WorkspaceContentSearchIndexMap.layer));
|
|
62901
63829
|
//#endregion
|
|
62902
63830
|
//#region src/workspace/WorkspaceFileSystem.ts
|
|
62903
63831
|
/**
|
|
@@ -62956,7 +63884,7 @@ Schema$1.Union([
|
|
|
62956
63884
|
]);
|
|
62957
63885
|
/** Service tag for workspace file operations. */
|
|
62958
63886
|
var WorkspaceFileSystem = class extends Context.Service()("@p4code/cli/workspace/WorkspaceFileSystem") {};
|
|
62959
|
-
const make$
|
|
63887
|
+
const make$21 = Effect.gen(function* () {
|
|
62960
63888
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
62961
63889
|
const path = yield* Path.Path;
|
|
62962
63890
|
const workspacePaths = yield* WorkspacePaths;
|
|
@@ -63100,7 +64028,7 @@ const make$20 = Effect.gen(function* () {
|
|
|
63100
64028
|
writeFile
|
|
63101
64029
|
});
|
|
63102
64030
|
});
|
|
63103
|
-
const layer$13 = Layer.effect(WorkspaceFileSystem, make$
|
|
64031
|
+
const layer$13 = Layer.effect(WorkspaceFileSystem, make$21);
|
|
63104
64032
|
//#endregion
|
|
63105
64033
|
//#region src/vcs/VcsStatusBroadcaster.ts
|
|
63106
64034
|
const DEFAULT_VCS_STATUS_REFRESH_INTERVAL = Duration.seconds(30);
|
|
@@ -63172,7 +64100,7 @@ function fingerprintStatusPart(status) {
|
|
|
63172
64100
|
return JSON.stringify(status);
|
|
63173
64101
|
}
|
|
63174
64102
|
const normalizeCwd = (cwd) => Effect.service(FileSystem.FileSystem).pipe(Effect.flatMap((fs) => fs.realPath(cwd)), Effect.orElseSucceed(() => cwd));
|
|
63175
|
-
const make$
|
|
64103
|
+
const make$20 = Effect.gen(function* () {
|
|
63176
64104
|
const workflow = yield* GitWorkflowService;
|
|
63177
64105
|
const fs = yield* FileSystem.FileSystem;
|
|
63178
64106
|
const changesPubSub = yield* Effect.acquireRelease(PubSub.unbounded(), (pubsub) => PubSub.shutdown(pubsub));
|
|
@@ -63396,7 +64324,7 @@ const make$19 = Effect.gen(function* () {
|
|
|
63396
64324
|
streamStatus
|
|
63397
64325
|
});
|
|
63398
64326
|
});
|
|
63399
|
-
const layer$12 = Layer.effect(VcsStatusBroadcaster, make$
|
|
64327
|
+
const layer$12 = Layer.effect(VcsStatusBroadcaster, make$20);
|
|
63400
64328
|
//#endregion
|
|
63401
64329
|
//#region src/vcs/VcsProvisioningService.ts
|
|
63402
64330
|
var VcsProvisioningService = class extends Context.Service()("@p4code/cli/vcs/VcsProvisioningService") {};
|
|
@@ -63409,7 +64337,7 @@ function resolveRequestedKind(kind) {
|
|
|
63409
64337
|
}));
|
|
63410
64338
|
return Effect.succeed(kind);
|
|
63411
64339
|
}
|
|
63412
|
-
const make$
|
|
64340
|
+
const make$19 = Effect.gen(function* () {
|
|
63413
64341
|
const registry = yield* VcsDriverRegistry;
|
|
63414
64342
|
const initRepository = Effect.fn("VcsProvisioningService.initRepository")(function* (input) {
|
|
63415
64343
|
const kind = yield* resolveRequestedKind(input.kind);
|
|
@@ -63417,11 +64345,11 @@ const make$18 = Effect.gen(function* () {
|
|
|
63417
64345
|
});
|
|
63418
64346
|
return VcsProvisioningService.of({ initRepository });
|
|
63419
64347
|
});
|
|
63420
|
-
const layer$11 = Layer.effect(VcsProvisioningService, make$
|
|
64348
|
+
const layer$11 = Layer.effect(VcsProvisioningService, make$19);
|
|
63421
64349
|
//#endregion
|
|
63422
64350
|
//#region src/review/ReviewService.ts
|
|
63423
64351
|
var ReviewService = class extends Context.Service()("@p4code/cli/review/ReviewService") {};
|
|
63424
|
-
const make$
|
|
64352
|
+
const make$18 = Effect.gen(function* () {
|
|
63425
64353
|
const config = yield* ServerConfig$1;
|
|
63426
64354
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
63427
64355
|
const path = yield* Path.Path;
|
|
@@ -63477,7 +64405,7 @@ const make$17 = Effect.gen(function* () {
|
|
|
63477
64405
|
});
|
|
63478
64406
|
return ReviewService.of({ getDiffPreview });
|
|
63479
64407
|
});
|
|
63480
|
-
const layer$10 = Layer.effect(ReviewService, make$
|
|
64408
|
+
const layer$10 = Layer.effect(ReviewService, make$18);
|
|
63481
64409
|
//#endregion
|
|
63482
64410
|
//#region src/diagnostics/ProcessDiagnostics.ts
|
|
63483
64411
|
const PROCESS_QUERY_TIMEOUT_MS = 1e3;
|
|
@@ -63772,7 +64700,7 @@ function assertDescendantPid(pid) {
|
|
|
63772
64700
|
}));
|
|
63773
64701
|
}));
|
|
63774
64702
|
}
|
|
63775
|
-
const make$
|
|
64703
|
+
const make$17 = Effect.gen(function* () {
|
|
63776
64704
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
63777
64705
|
const read = Effect.gen(function* () {
|
|
63778
64706
|
const readAt = yield* DateTime.now;
|
|
@@ -63816,7 +64744,7 @@ const make$16 = Effect.gen(function* () {
|
|
|
63816
64744
|
signal
|
|
63817
64745
|
});
|
|
63818
64746
|
});
|
|
63819
|
-
const layer$9 = Layer.effect(ProcessDiagnostics, make$
|
|
64747
|
+
const layer$9 = Layer.effect(ProcessDiagnostics, make$17);
|
|
63820
64748
|
//#endregion
|
|
63821
64749
|
//#region src/diagnostics/ProcessResourceMonitor.ts
|
|
63822
64750
|
const SAMPLE_INTERVAL_MS = 5e3;
|
|
@@ -63967,7 +64895,7 @@ function aggregateProcessResourceHistory(input) {
|
|
|
63967
64895
|
}) : Option.none()
|
|
63968
64896
|
};
|
|
63969
64897
|
}
|
|
63970
|
-
const make$
|
|
64898
|
+
const make$16 = Effect.gen(function* () {
|
|
63971
64899
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
63972
64900
|
const state = yield* Ref.make({
|
|
63973
64901
|
samples: [],
|
|
@@ -64016,7 +64944,7 @@ const make$15 = Effect.gen(function* () {
|
|
|
64016
64944
|
});
|
|
64017
64945
|
return ProcessResourceMonitor.of({ readHistory });
|
|
64018
64946
|
});
|
|
64019
|
-
const layer$8 = Layer.effect(ProcessResourceMonitor, make$
|
|
64947
|
+
const layer$8 = Layer.effect(ProcessResourceMonitor, make$16);
|
|
64020
64948
|
//#endregion
|
|
64021
64949
|
//#region src/diagnostics/TraceDiagnostics.ts
|
|
64022
64950
|
var TraceFileReadError = class extends Schema$1.TaggedErrorClass()("TraceFileReadError", {
|
|
@@ -64264,7 +65192,7 @@ function readTraceFile(fileSystem, path) {
|
|
|
64264
65192
|
cause
|
|
64265
65193
|
})) }));
|
|
64266
65194
|
}
|
|
64267
|
-
const make$
|
|
65195
|
+
const make$15 = Effect.gen(function* () {
|
|
64268
65196
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
64269
65197
|
const read = Effect.fn("TraceDiagnostics.read")(function* (options) {
|
|
64270
65198
|
const readAt = options.readAt ?? (yield* DateTime.now);
|
|
@@ -64308,7 +65236,7 @@ const make$14 = Effect.gen(function* () {
|
|
|
64308
65236
|
});
|
|
64309
65237
|
return TraceDiagnostics.of({ read });
|
|
64310
65238
|
});
|
|
64311
|
-
const layer$7 = Layer.effect(TraceDiagnostics, make$
|
|
65239
|
+
const layer$7 = Layer.effect(TraceDiagnostics, make$15);
|
|
64312
65240
|
function readTraceDiagnostics(options) {
|
|
64313
65241
|
return Effect.gen(function* () {
|
|
64314
65242
|
return yield* (yield* TraceDiagnostics).read(options);
|
|
@@ -64332,7 +65260,7 @@ const VCS_PROBES = [{
|
|
|
64332
65260
|
installHint: "Install Jujutsu with `brew install jj` or from https://github.com/jj-vcs/jj."
|
|
64333
65261
|
}];
|
|
64334
65262
|
var SourceControlDiscovery = class extends Context.Service()("@p4code/cli/sourceControl/SourceControlDiscovery") {};
|
|
64335
|
-
const make$
|
|
65263
|
+
const make$14 = Effect.gen(function* () {
|
|
64336
65264
|
const config = yield* ServerConfig$1;
|
|
64337
65265
|
const process = yield* VcsProcess;
|
|
64338
65266
|
const sourceControlProviders = yield* SourceControlProviderRegistry;
|
|
@@ -64381,7 +65309,7 @@ const make$13 = Effect.gen(function* () {
|
|
|
64381
65309
|
sourceControlProviders: sourceControlProviders.discover
|
|
64382
65310
|
}) });
|
|
64383
65311
|
});
|
|
64384
|
-
const layer$6 = Layer.effect(SourceControlDiscovery, make$
|
|
65312
|
+
const layer$6 = Layer.effect(SourceControlDiscovery, make$14);
|
|
64385
65313
|
//#endregion
|
|
64386
65314
|
//#region src/sourceControl/SourceControlRepositoryService.ts
|
|
64387
65315
|
const isSourceControlRepositoryError = Schema$1.is(SourceControlRepositoryError);
|
|
@@ -64414,7 +65342,7 @@ function expandHomePath(input, path) {
|
|
|
64414
65342
|
if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
|
|
64415
65343
|
return input;
|
|
64416
65344
|
}
|
|
64417
|
-
const make$
|
|
65345
|
+
const make$13 = Effect.gen(function* () {
|
|
64418
65346
|
const config = yield* ServerConfig$1;
|
|
64419
65347
|
const fileSystem = yield* FileSystem.FileSystem;
|
|
64420
65348
|
const git = yield* GitVcsDriver;
|
|
@@ -64553,7 +65481,7 @@ const make$12 = Effect.gen(function* () {
|
|
|
64553
65481
|
publishRepository: (input) => publishRepository(input).pipe(mapRepositoryError("publishRepository", input.provider))
|
|
64554
65482
|
});
|
|
64555
65483
|
});
|
|
64556
|
-
const layer$5 = Layer.effect(SourceControlRepositoryService, make$
|
|
65484
|
+
const layer$5 = Layer.effect(SourceControlRepositoryService, make$13);
|
|
64557
65485
|
//#endregion
|
|
64558
65486
|
//#region src/ws.ts
|
|
64559
65487
|
/** Matches `p4c hub token add`, so a token minted here and one minted there are the same thing. */
|
|
@@ -64659,6 +65587,7 @@ function isThreadDetailEvent(event) {
|
|
|
64659
65587
|
}
|
|
64660
65588
|
const PROVIDER_STATUS_DEBOUNCE_MS = 200;
|
|
64661
65589
|
const SHELL_RESUME_MAX_GAP = 1e3;
|
|
65590
|
+
const THREAD_RESUME_MAX_GAP = 1e3;
|
|
64662
65591
|
const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
|
|
64663
65592
|
[ORCHESTRATION_WS_METHODS.dispatchCommand, AuthOrchestrationOperateScope],
|
|
64664
65593
|
[ORCHESTRATION_WS_METHODS.getTurnDiff, AuthOrchestrationReadScope],
|
|
@@ -64745,6 +65674,7 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
|
|
|
64745
65674
|
[WS_METHODS.projectsListEntries, AuthOrchestrationReadScope],
|
|
64746
65675
|
[WS_METHODS.projectsReadFile, AuthOrchestrationReadScope],
|
|
64747
65676
|
[WS_METHODS.projectsSearchEntries, AuthOrchestrationReadScope],
|
|
65677
|
+
[WS_METHODS.projectsSearchContents, AuthOrchestrationReadScope],
|
|
64748
65678
|
[WS_METHODS.projectsWriteFile, AuthOrchestrationOperateScope],
|
|
64749
65679
|
[WS_METHODS.shellOpenInEditor, AuthOrchestrationOperateScope],
|
|
64750
65680
|
[WS_METHODS.filesystemBrowse, AuthOrchestrationReadScope],
|
|
@@ -65361,15 +66291,19 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
65361
66291
|
const bufferedLiveStream = liveBuffer.stream;
|
|
65362
66292
|
if (input.afterSequence !== void 0) {
|
|
65363
66293
|
const afterSequence = input.afterSequence;
|
|
65364
|
-
const
|
|
65365
|
-
|
|
65366
|
-
|
|
65367
|
-
|
|
65368
|
-
|
|
65369
|
-
|
|
65370
|
-
|
|
65371
|
-
|
|
65372
|
-
|
|
66294
|
+
const headSequence = yield* orchestrationEngine.latestSequence;
|
|
66295
|
+
const replayGap = headSequence - afterSequence;
|
|
66296
|
+
if (replayGap >= 0 && replayGap <= THREAD_RESUME_MAX_GAP) {
|
|
66297
|
+
const catchUpStream = (replayGap === 0 ? Stream.empty : orchestrationEngine.readEvents(afterSequence, replayGap)).pipe(Stream.takeWhile((event) => event.sequence <= headSequence), Stream.filter(isThisThreadDetailEvent), Stream.map((event) => ({
|
|
66298
|
+
kind: "event",
|
|
66299
|
+
event: projectActivityEvent(event)
|
|
66300
|
+
})), Stream.mapError((cause) => new OrchestrationGetSnapshotError({
|
|
66301
|
+
message: `Failed to replay thread ${input.threadId} events`,
|
|
66302
|
+
cause
|
|
66303
|
+
})));
|
|
66304
|
+
const afterCatchUp = input.requestCompletionMarker === true ? Stream.concat(Stream.fromEffect(liveBuffer.offerAndWait({ kind: "synchronized" }).pipe(Effect.andThen(liveBuffer.takeAll))).pipe(Stream.flatMap((items) => Stream.fromIterable(items))), bufferedLiveStream) : bufferedLiveStream;
|
|
66305
|
+
return Stream.concat(catchUpStream, afterCatchUp);
|
|
66306
|
+
}
|
|
65373
66307
|
}
|
|
65374
66308
|
const snapshot = yield* projectionSnapshotQuery.getThreadDetailSnapshot(input.threadId, input.turnLimit === void 0 ? void 0 : { turnLimit: input.turnLimit }).pipe(Effect.mapError((cause) => new OrchestrationGetSnapshotError({
|
|
65375
66309
|
message: `Failed to load thread ${input.threadId}`,
|
|
@@ -65637,6 +66571,13 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
|
|
|
65637
66571
|
...projectEntriesFailureContext(cause),
|
|
65638
66572
|
cause
|
|
65639
66573
|
}))), { "rpc.aggregate": "workspace" }),
|
|
66574
|
+
[WS_METHODS.projectsSearchContents]: (input) => observeRpcEffect$1(WS_METHODS.projectsSearchContents, workspaceEntries.searchContents(input).pipe(Effect.mapError((cause) => new ProjectSearchEntriesError({
|
|
66575
|
+
cwd: input.cwd,
|
|
66576
|
+
queryLength: input.query.length,
|
|
66577
|
+
limit: input.limit,
|
|
66578
|
+
...projectEntriesFailureContext(cause),
|
|
66579
|
+
cause
|
|
66580
|
+
}))), { "rpc.aggregate": "workspace" }),
|
|
65640
66581
|
[WS_METHODS.projectsListEntries]: (input) => observeRpcEffect$1(WS_METHODS.projectsListEntries, workspaceEntries.list(input).pipe(Effect.mapError((cause) => new ProjectListEntriesError({
|
|
65641
66582
|
...input,
|
|
65642
66583
|
...projectEntriesFailureContext(cause),
|
|
@@ -65857,7 +66798,7 @@ function toPersistenceSqlOrDecodeError(sqlOperation, decodeOperation, correlatio
|
|
|
65857
66798
|
cause
|
|
65858
66799
|
});
|
|
65859
66800
|
}
|
|
65860
|
-
const make$
|
|
66801
|
+
const make$12 = Effect.gen(function* () {
|
|
65861
66802
|
const sql = yield* SqlClient.SqlClient;
|
|
65862
66803
|
const upsertRuntimeRow = SqlSchema.void({
|
|
65863
66804
|
Request: ProviderSessionRuntimeDbRowSchema,
|
|
@@ -65960,7 +66901,7 @@ const make$11 = Effect.gen(function* () {
|
|
|
65960
66901
|
deleteByThreadId
|
|
65961
66902
|
};
|
|
65962
66903
|
});
|
|
65963
|
-
const layer$4 = Layer.effect(ProviderSessionRuntimeRepository, make$
|
|
66904
|
+
const layer$4 = Layer.effect(ProviderSessionRuntimeRepository, make$12);
|
|
65964
66905
|
//#endregion
|
|
65965
66906
|
//#region src/provider/Errors.ts
|
|
65966
66907
|
/**
|
|
@@ -66612,7 +67553,7 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66612
67553
|
const httpServer = yield* HttpServer.HttpServer;
|
|
66613
67554
|
const state = yield* SynchronizedRef.make({
|
|
66614
67555
|
records: /* @__PURE__ */ new Map(),
|
|
66615
|
-
|
|
67556
|
+
spawnedThreads: /* @__PURE__ */ new Map()
|
|
66616
67557
|
});
|
|
66617
67558
|
const currentTimeMillis = options.now ? Effect.sync(options.now) : Clock.currentTimeMillis;
|
|
66618
67559
|
const livenessWindowMs = options.livenessWindowMs ?? DEFAULT_LIVENESS_WINDOW_MS;
|
|
@@ -66637,7 +67578,7 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66637
67578
|
if (watchThreadIds.size > 0) capabilities.add("watch");
|
|
66638
67579
|
if (adviseThreadIds.size > 0) capabilities.add("advise");
|
|
66639
67580
|
const threadId = ThreadId.make(request.threadId);
|
|
66640
|
-
const scopeWith = (mayCreateThreads) => ({
|
|
67581
|
+
const scopeWith = (mayCreateThreads, mayCreateFusionPairs) => ({
|
|
66641
67582
|
environmentId,
|
|
66642
67583
|
threadId,
|
|
66643
67584
|
providerSessionId,
|
|
@@ -66646,19 +67587,20 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66646
67587
|
...watchThreadIds.size > 0 ? { watchThreadIds } : {},
|
|
66647
67588
|
...adviseThreadIds.size > 0 ? { adviseThreadIds } : {},
|
|
66648
67589
|
mayCreateThreads,
|
|
67590
|
+
mayCreateFusionPairs,
|
|
66649
67591
|
issuedAt
|
|
66650
67592
|
});
|
|
66651
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67593
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66652
67594
|
const next = new Map(pruneDead(records, issuedAt));
|
|
66653
67595
|
next.set(tokenHash, {
|
|
66654
67596
|
tokenHash,
|
|
66655
|
-
scope: scopeWith(!
|
|
67597
|
+
scope: scopeWith(!spawnedThreads.has(threadId), spawnedThreads.get(threadId) === true),
|
|
66656
67598
|
controlThreadIds: /* @__PURE__ */ new Set(),
|
|
66657
67599
|
lastAliveAt: issuedAt
|
|
66658
67600
|
});
|
|
66659
67601
|
return {
|
|
66660
67602
|
records: next,
|
|
66661
|
-
|
|
67603
|
+
spawnedThreads
|
|
66662
67604
|
};
|
|
66663
67605
|
});
|
|
66664
67606
|
return { config: {
|
|
@@ -66674,12 +67616,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66674
67616
|
if (rawToken.length === 0) return void 0;
|
|
66675
67617
|
const tokenHash = yield* hashToken(rawToken);
|
|
66676
67618
|
const timestamp = yield* currentTimeMillis;
|
|
66677
|
-
return yield* SynchronizedRef.modify(state, ({ records,
|
|
67619
|
+
return yield* SynchronizedRef.modify(state, ({ records, spawnedThreads }) => {
|
|
66678
67620
|
const current = pruneDead(records, timestamp);
|
|
66679
67621
|
const record = current.get(tokenHash);
|
|
66680
67622
|
if (!record) return [void 0, {
|
|
66681
67623
|
records: current,
|
|
66682
|
-
|
|
67624
|
+
spawnedThreads
|
|
66683
67625
|
}];
|
|
66684
67626
|
const next = new Map(current);
|
|
66685
67627
|
next.set(tokenHash, {
|
|
@@ -66693,13 +67635,13 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66693
67635
|
watchThreadIds: /* @__PURE__ */ new Set([...record.scope.watchThreadIds ?? [], ...record.controlThreadIds])
|
|
66694
67636
|
}, {
|
|
66695
67637
|
records: next,
|
|
66696
|
-
|
|
67638
|
+
spawnedThreads
|
|
66697
67639
|
}];
|
|
66698
67640
|
});
|
|
66699
67641
|
});
|
|
66700
67642
|
const touch = Effect.fn("McpSessionRegistry.touch")(function* (threadId) {
|
|
66701
67643
|
const timestamp = yield* currentTimeMillis;
|
|
66702
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67644
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66703
67645
|
const current = pruneDead(records, timestamp);
|
|
66704
67646
|
const next = new Map(current);
|
|
66705
67647
|
for (const [tokenHash, record] of current) if (record.scope.threadId === threadId) next.set(tokenHash, {
|
|
@@ -66708,12 +67650,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66708
67650
|
});
|
|
66709
67651
|
return {
|
|
66710
67652
|
records: next,
|
|
66711
|
-
|
|
67653
|
+
spawnedThreads
|
|
66712
67654
|
};
|
|
66713
67655
|
});
|
|
66714
67656
|
});
|
|
66715
67657
|
const grantWatchThread = Effect.fn("McpSessionRegistry.grantWatchThread")(function* ({ watcherThreadId, watchedThreadId }) {
|
|
66716
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67658
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66717
67659
|
const next = new Map(records);
|
|
66718
67660
|
for (const [tokenHash, record] of records) {
|
|
66719
67661
|
if (record.scope.threadId !== watcherThreadId) continue;
|
|
@@ -66728,12 +67670,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66728
67670
|
}
|
|
66729
67671
|
return {
|
|
66730
67672
|
records: next,
|
|
66731
|
-
|
|
67673
|
+
spawnedThreads
|
|
66732
67674
|
};
|
|
66733
67675
|
});
|
|
66734
67676
|
});
|
|
66735
67677
|
const revokeWatchThread = Effect.fn("McpSessionRegistry.revokeWatchThread")(function* ({ watcherThreadId, watchedThreadId }) {
|
|
66736
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67678
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66737
67679
|
const next = new Map(records);
|
|
66738
67680
|
for (const [tokenHash, record] of records) {
|
|
66739
67681
|
if (record.scope.threadId !== watcherThreadId) continue;
|
|
@@ -66756,12 +67698,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66756
67698
|
}
|
|
66757
67699
|
return {
|
|
66758
67700
|
records: next,
|
|
66759
|
-
|
|
67701
|
+
spawnedThreads
|
|
66760
67702
|
};
|
|
66761
67703
|
});
|
|
66762
67704
|
});
|
|
66763
67705
|
const grantAdviseThread = Effect.fn("McpSessionRegistry.grantAdviseThread")(function* ({ watcherThreadId, advisedThreadId }) {
|
|
66764
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67706
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66765
67707
|
const next = new Map(records);
|
|
66766
67708
|
for (const [tokenHash, record] of records) {
|
|
66767
67709
|
if (record.scope.threadId !== watcherThreadId) continue;
|
|
@@ -66776,12 +67718,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66776
67718
|
}
|
|
66777
67719
|
return {
|
|
66778
67720
|
records: next,
|
|
66779
|
-
|
|
67721
|
+
spawnedThreads
|
|
66780
67722
|
};
|
|
66781
67723
|
});
|
|
66782
67724
|
});
|
|
66783
67725
|
const revokeAdviseThread = Effect.fn("McpSessionRegistry.revokeAdviseThread")(function* ({ watcherThreadId, advisedThreadId }) {
|
|
66784
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67726
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66785
67727
|
const next = new Map(records);
|
|
66786
67728
|
for (const [tokenHash, record] of records) {
|
|
66787
67729
|
if (record.scope.threadId !== watcherThreadId) continue;
|
|
@@ -66804,12 +67746,12 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66804
67746
|
}
|
|
66805
67747
|
return {
|
|
66806
67748
|
records: next,
|
|
66807
|
-
|
|
67749
|
+
spawnedThreads
|
|
66808
67750
|
};
|
|
66809
67751
|
});
|
|
66810
67752
|
});
|
|
66811
67753
|
const recordSpawnedThread = Effect.fn("McpSessionRegistry.recordSpawnedThread")(function* (input) {
|
|
66812
|
-
yield* SynchronizedRef.update(state, ({ records,
|
|
67754
|
+
yield* SynchronizedRef.update(state, ({ records, spawnedThreads }) => {
|
|
66813
67755
|
const next = new Map(records);
|
|
66814
67756
|
for (const [tokenHash, record] of records) if (record.scope.providerSessionId === input.providerSessionId) next.set(tokenHash, {
|
|
66815
67757
|
...record,
|
|
@@ -66817,13 +67759,13 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66817
67759
|
});
|
|
66818
67760
|
return {
|
|
66819
67761
|
records: next,
|
|
66820
|
-
|
|
67762
|
+
spawnedThreads: new Map([...spawnedThreads, [input.threadId, input.mayCreateFusionPairs === true]])
|
|
66821
67763
|
};
|
|
66822
67764
|
});
|
|
66823
67765
|
});
|
|
66824
|
-
const revokeWhere = (predicate) => SynchronizedRef.update(state, ({ records,
|
|
67766
|
+
const revokeWhere = (predicate) => SynchronizedRef.update(state, ({ records, spawnedThreads }) => ({
|
|
66825
67767
|
records: new Map(Array.from(records).filter(([, record]) => !predicate(record))),
|
|
66826
|
-
|
|
67768
|
+
spawnedThreads
|
|
66827
67769
|
}));
|
|
66828
67770
|
return McpSessionRegistry.of({
|
|
66829
67771
|
issue,
|
|
@@ -66840,19 +67782,19 @@ const makeWithOptions = Effect.fn("McpSessionRegistry.make")(function* (options
|
|
|
66840
67782
|
revokeThread: Effect.fn("McpSessionRegistry.revokeThread")(function* (threadId) {
|
|
66841
67783
|
yield* revokeWhere((record) => record.scope.threadId === threadId);
|
|
66842
67784
|
}),
|
|
66843
|
-
revokeAll: SynchronizedRef.update(state, ({
|
|
67785
|
+
revokeAll: SynchronizedRef.update(state, ({ spawnedThreads }) => ({
|
|
66844
67786
|
records: /* @__PURE__ */ new Map(),
|
|
66845
|
-
|
|
67787
|
+
spawnedThreads
|
|
66846
67788
|
}))
|
|
66847
67789
|
});
|
|
66848
67790
|
});
|
|
66849
67791
|
let activeMcpSessionRegistry;
|
|
66850
|
-
const make$
|
|
67792
|
+
const make$11 = Effect.acquireRelease(makeWithOptions().pipe(Effect.tap((registry) => Effect.sync(() => {
|
|
66851
67793
|
activeMcpSessionRegistry = registry;
|
|
66852
67794
|
}))), (registry) => Effect.sync(() => {
|
|
66853
67795
|
if (activeMcpSessionRegistry === registry) activeMcpSessionRegistry = void 0;
|
|
66854
67796
|
}));
|
|
66855
|
-
const layer$3 = Layer.effect(McpSessionRegistry, make$
|
|
67797
|
+
const layer$3 = Layer.effect(McpSessionRegistry, make$11);
|
|
66856
67798
|
const issueActiveMcpCredential = (request) => activeMcpSessionRegistry ? activeMcpSessionRegistry.revokeThread(request.threadId).pipe(Effect.andThen(activeMcpSessionRegistry.issue(request))) : Effect.sync(() => void 0);
|
|
66857
67799
|
/**
|
|
66858
67800
|
* Refreshes the liveness of a thread's MCP credential. Called on every provider
|
|
@@ -67561,6 +68503,13 @@ const makeProviderSessionReaper = (options) => Effect.gen(function* () {
|
|
|
67561
68503
|
});
|
|
67562
68504
|
continue;
|
|
67563
68505
|
}
|
|
68506
|
+
if (thread?.backgroundLiveness != null) {
|
|
68507
|
+
yield* Effect.logDebug("provider.session.reaper.skipped-background-work", {
|
|
68508
|
+
threadId: binding.threadId,
|
|
68509
|
+
backgroundLiveness: thread.backgroundLiveness
|
|
68510
|
+
});
|
|
68511
|
+
continue;
|
|
68512
|
+
}
|
|
67564
68513
|
if (yield* providerService.stopSession({ threadId: binding.threadId }).pipe(Effect.tap(() => Effect.logInfo("provider.session.reaped", {
|
|
67565
68514
|
threadId: binding.threadId,
|
|
67566
68515
|
provider: binding.provider,
|
|
@@ -67578,14 +68527,18 @@ const makeProviderSessionReaper = (options) => Effect.gen(function* () {
|
|
|
67578
68527
|
totalBindings: bindings.length
|
|
67579
68528
|
});
|
|
67580
68529
|
});
|
|
68530
|
+
const sweepSafely = () => sweep.pipe(Effect.catch((error) => Effect.logWarning("provider.session.reaper.sweep-failed", { error })), Effect.catchDefect((defect) => Effect.logWarning("provider.session.reaper.sweep-defect", { defect })));
|
|
67581
68531
|
const start = () => Effect.gen(function* () {
|
|
67582
|
-
yield* Effect.forkScoped(
|
|
68532
|
+
yield* Effect.forkScoped(sweepSafely().pipe(Effect.repeat(Schedule.spaced(Duration.millis(sweepIntervalMs)))));
|
|
67583
68533
|
yield* Effect.logInfo("provider.session.reaper.started", {
|
|
67584
68534
|
inactivityThresholdMs,
|
|
67585
68535
|
sweepIntervalMs
|
|
67586
68536
|
});
|
|
67587
68537
|
});
|
|
67588
|
-
return {
|
|
68538
|
+
return {
|
|
68539
|
+
start,
|
|
68540
|
+
sweep: sweepSafely
|
|
68541
|
+
};
|
|
67589
68542
|
});
|
|
67590
68543
|
const makeProviderSessionReaperLive = (options) => Layer.effect(ProviderSessionReaper, makeProviderSessionReaper(options));
|
|
67591
68544
|
const ProviderSessionReaperLive = makeProviderSessionReaperLive();
|
|
@@ -69767,7 +70720,7 @@ function formatAskUserQuestionAnswers(answers) {
|
|
|
69767
70720
|
* only a one-line reference and the mutable `[fusion-pair]` metadata.
|
|
69768
70721
|
*/
|
|
69769
70722
|
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.`;
|
|
69770
|
-
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. To resume supervision, read builder
|
|
70723
|
+
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. 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.`;
|
|
69771
70724
|
/**
|
|
69772
70725
|
* The one-line stand-in for the full block on a message whose session already
|
|
69773
70726
|
* carries the role instructions.
|
|
@@ -91028,7 +91981,7 @@ const makeTerminationError$1 = (handle) => Effect.match(handle.exitCode, {
|
|
|
91028
91981
|
//#endregion
|
|
91029
91982
|
//#region ../../packages/effect-codex-app-server/src/client.ts
|
|
91030
91983
|
var CodexAppServerClient = class extends Context.Service()("effect-codex-app-server/client/CodexAppServerClient") {};
|
|
91031
|
-
const make$
|
|
91984
|
+
const make$10 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(function* (stdio, options = {}, terminationError) {
|
|
91032
91985
|
const requestHandlers = /* @__PURE__ */ new Map();
|
|
91033
91986
|
const notificationHandlers = /* @__PURE__ */ new Map();
|
|
91034
91987
|
let unknownRequestHandler;
|
|
@@ -91095,7 +92048,7 @@ const make$9 = Effect.fn("effect-codex-app-server/CodexAppServerClient.make")(fu
|
|
|
91095
92048
|
const layerChildProcess$1 = (handle, options = {}) => Layer.effect(CodexAppServerClient, makeChildProcessClient(handle, options));
|
|
91096
92049
|
const makeChildProcessClient = Effect.fn("effect-codex-app-server/CodexAppServerClient.makeChildProcessClient")(function* (handle, options) {
|
|
91097
92050
|
yield* Stream.runDrain(handle.stderr).pipe(Effect.ignore, Effect.forkScoped);
|
|
91098
|
-
return yield* make$
|
|
92051
|
+
return yield* make$10(makeChildStdio$1(handle), options, makeTerminationError$1(handle));
|
|
91099
92052
|
});
|
|
91100
92053
|
const resolveCodexLaunchArgs = (launchArgs, environment = process.env) => environment["P4CODE_CODEX_LAUNCH_ARGS"]?.trim() || launchArgs?.trim() || "";
|
|
91101
92054
|
const codexLaunchArgv = (launchArgs) => tokenizeCliArgs(launchArgs);
|
|
@@ -92118,6 +93071,8 @@ Default mode active; prior mode instructions inactive. Only developer \`<collabo
|
|
|
92118
93071
|
|
|
92119
93072
|
Prefer reasonable assumptions and execution. Ask only when local discovery cannot answer and a reasonable assumption is risky.
|
|
92120
93073
|
|
|
93074
|
+
For multi-step work, keep task phases visible with native \`update_plan\`. If that tool is unavailable, use \`mcp__p4_code__thread_plan_update\` instead: send the complete ordered \`plan\` array of \`{ step, status }\`, with statuses \`pending\`, \`in_progress\`, or \`completed\`. Update it as phases finish. Prose alone does not populate the Tasks banner. This fallback tracks this conversation, not task-board tickets.
|
|
93075
|
+
|
|
92121
93076
|
${CODEX_STRUCTURED_USER_QUESTIONS}
|
|
92122
93077
|
${P4_CODE_BROWSER_TOOL_INSTRUCTIONS}
|
|
92123
93078
|
</collaboration_mode>`;
|
|
@@ -97898,7 +98853,7 @@ const makeTerminationError = (handle) => Effect.match(handle.exitCode, {
|
|
|
97898
98853
|
//#endregion
|
|
97899
98854
|
//#region ../../packages/effect-acp/src/client.ts
|
|
97900
98855
|
var AcpClient = class extends Context.Service()("effect-acp/client/AcpClient") {};
|
|
97901
|
-
const make$
|
|
98856
|
+
const make$9 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options = {}, terminationError) {
|
|
97902
98857
|
const coreHandlers = {};
|
|
97903
98858
|
const notificationHandlers = {
|
|
97904
98859
|
sessionUpdate: {
|
|
@@ -98056,7 +99011,7 @@ const make$8 = Effect.fn("effect-acp/AcpClient.make")(function* (stdio, options
|
|
|
98056
99011
|
const layerChildProcess = (handle, options = {}) => {
|
|
98057
99012
|
const stdio = makeChildStdio(handle);
|
|
98058
99013
|
const terminationError = makeTerminationError(handle);
|
|
98059
|
-
return Layer.effect(AcpClient, make$
|
|
99014
|
+
return Layer.effect(AcpClient, make$9(stdio, options, terminationError));
|
|
98060
99015
|
};
|
|
98061
99016
|
//#endregion
|
|
98062
99017
|
//#region ../../packages/shared/src/toolActivity.ts
|
|
@@ -98516,7 +99471,7 @@ function formatConfigOptionValue(value) {
|
|
|
98516
99471
|
const defaultSessionLoadTimeout = Duration.seconds(90);
|
|
98517
99472
|
const defaultSessionLoadReplayIdleGap = Duration.seconds(2);
|
|
98518
99473
|
var AcpSessionRuntime = class extends Context.Service()("@p4code/cli/provider/acp/AcpSessionRuntime") {};
|
|
98519
|
-
const make$
|
|
99474
|
+
const make$8 = (options) => Effect.gen(function* () {
|
|
98520
99475
|
const crypto = yield* Crypto.Crypto;
|
|
98521
99476
|
const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
|
|
98522
99477
|
const runtimeScope = yield* Scope.Scope;
|
|
@@ -98832,7 +99787,7 @@ const make$7 = (options) => Effect.gen(function* () {
|
|
|
98832
99787
|
notify: acp.raw.notify
|
|
98833
99788
|
};
|
|
98834
99789
|
});
|
|
98835
|
-
const layer$2 = (options) => Layer.effect(AcpSessionRuntime, make$
|
|
99790
|
+
const layer$2 = (options) => Layer.effect(AcpSessionRuntime, make$8(options));
|
|
98836
99791
|
function sessionConfigOptionsFromSetup(response) {
|
|
98837
99792
|
return response?.configOptions ?? [];
|
|
98838
99793
|
}
|
|
@@ -106293,7 +107248,7 @@ const stringField = (record, key) => {
|
|
|
106293
107248
|
const value = record[key];
|
|
106294
107249
|
return typeof value === "string" && value.trim().length > 0 ? value.trim() : void 0;
|
|
106295
107250
|
};
|
|
106296
|
-
const make$
|
|
107251
|
+
const make$7 = Effect.gen(function* () {
|
|
106297
107252
|
const linear = yield* LinearClient;
|
|
106298
107253
|
return { resolve: Effect.fn("TicketResolver.resolve")(function* (reference) {
|
|
106299
107254
|
const identifier = parseTicketReference(reference);
|
|
@@ -106324,7 +107279,7 @@ const make$6 = Effect.gen(function* () {
|
|
|
106324
107279
|
};
|
|
106325
107280
|
}) };
|
|
106326
107281
|
});
|
|
106327
|
-
const layer$1 = Layer.effect(TicketResolver, make$
|
|
107282
|
+
const layer$1 = Layer.effect(TicketResolver, make$7);
|
|
106328
107283
|
//#endregion
|
|
106329
107284
|
//#region src/mcp/toolkits/tasks/tools.ts
|
|
106330
107285
|
const dependencies = [McpInvocationContext, TaskRepository];
|
|
@@ -106863,7 +107818,7 @@ const AskUserQuestionTool = Tool.make("ask_user_question", {
|
|
|
106863
107818
|
]
|
|
106864
107819
|
}).annotate(Tool.Title, "Ask user question").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
|
|
106865
107820
|
const ThreadSpawnTool = Tool.make("thread_spawn", {
|
|
106866
|
-
description: "Start a new agent thread and send it a first message, then return its id. Use it to hand a piece of work to a fresh thread - a subtask you just planned, a job that wants its own transcript. Set fusionWatcher true for a
|
|
107821
|
+
description: "Start a new agent thread and send it a first message, then return its id. Use it to hand a piece of work to a fresh thread - a subtask you just planned, a job that wants its own transcript. Set fusion true to create two new threads as a separate Fusion pair and start its builder with prompt, even when this thread already belongs to a pair. Set fusionWatcher true only for a supervisor to pair with the current thread. Both use saved Fusion role models unless overridden. Act on the user's request; no special command syntax is required. The new thread inherits this one's project, model, permission mode, interaction mode, compression and subagent policy, and every one of those can be set here instead - what you set is already in force for the first turn, so a thread never has to be corrected after it starts. Set modelSelection to run it on another model: give the model id, and leave instanceId out to keep this thread's provider instance. Once started it can be watched with thread_watch_events and changed later with thread_configure. A thread that was itself started this way cannot start another.",
|
|
106867
107822
|
parameters: ThreadSpawnInput,
|
|
106868
107823
|
success: ThreadSpawnResult,
|
|
106869
107824
|
failure: ThreadControlToolError,
|
|
@@ -106871,20 +107826,19 @@ const ThreadSpawnTool = Tool.make("thread_spawn", {
|
|
|
106871
107826
|
McpInvocationContext,
|
|
106872
107827
|
McpSessionRegistry,
|
|
106873
107828
|
OrchestrationEngineService,
|
|
106874
|
-
ProjectionSnapshotQuery,
|
|
106875
107829
|
ProjectionThreadRepository,
|
|
107830
|
+
ServerSettingsService,
|
|
106876
107831
|
Crypto.Crypto
|
|
106877
107832
|
]
|
|
106878
107833
|
}).annotate(Tool.Title, "Start a thread").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
|
|
106879
107834
|
const ThreadPairCreateTool = Tool.make("thread_pair_create", {
|
|
106880
|
-
description: "Create a persisted Fusion pair between this agent session's own thread as builder and a supervisor it previously created with thread_spawn.
|
|
107835
|
+
description: "Create a persisted Fusion pair between this agent session's own thread as builder and a supervisor it previously created with thread_spawn. Act on the user's request; no special command syntax is required. The current thread must not already belong to an active Fusion pair. Successful creation automatically continues the builder, so never ask the user to resend the task.",
|
|
106881
107836
|
parameters: ThreadPairCreateInput,
|
|
106882
107837
|
success: ThreadPairCreateResult,
|
|
106883
107838
|
failure: ThreadControlToolError,
|
|
106884
107839
|
dependencies: [
|
|
106885
107840
|
McpInvocationContext,
|
|
106886
107841
|
OrchestrationEngineService,
|
|
106887
|
-
ProjectionSnapshotQuery,
|
|
106888
107842
|
Crypto.Crypto
|
|
106889
107843
|
]
|
|
106890
107844
|
}).annotate(Tool.Title, "Create a Fusion pair").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
|
|
@@ -106972,7 +107926,19 @@ const AssetCompressTool = Tool.make("asset_compress", {
|
|
|
106972
107926
|
Path.Path
|
|
106973
107927
|
]
|
|
106974
107928
|
}).annotate(Tool.Title, "Compress an asset").annotate(Tool.Readonly, false).annotate(Tool.Destructive, true).annotate(Tool.Idempotent, false);
|
|
106975
|
-
const
|
|
107929
|
+
const ThreadPlanUpdateTool = Tool.make("thread_plan_update", {
|
|
107930
|
+
description: "Update the current thread's Tasks banner when your provider has no native update_plan or todo tool. Send the complete ordered phase list on every update, with at most one in_progress phase. Use short outcome titles. An empty plan clears the banner. This tracks conversation progress, not task-board tickets.",
|
|
107931
|
+
parameters: ThreadPlanUpdateInput,
|
|
107932
|
+
success: ThreadPlanUpdateResult,
|
|
107933
|
+
failure: ThreadControlToolError,
|
|
107934
|
+
dependencies: [
|
|
107935
|
+
McpInvocationContext,
|
|
107936
|
+
OrchestrationEngineService,
|
|
107937
|
+
ProjectionThreadRepository,
|
|
107938
|
+
Crypto.Crypto
|
|
107939
|
+
]
|
|
107940
|
+
}).annotate(Tool.Title, "Update task phases").annotate(Tool.Readonly, false).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, false);
|
|
107941
|
+
const ThreadToolkit = Toolkit.make(ThreadPlanUpdateTool, AskUserQuestionTool, ThreadSpawnTool, ThreadPairCreateTool, ThreadConfigureTool, ThreadSettleTool, ThreadCleanupTool, ThreadSnoozeTool, ThreadRenameTool, MemoryAppendTool, AssetCompressTool);
|
|
106976
107942
|
//#endregion
|
|
106977
107943
|
//#region src/orchestration/pendingMcpUserInputs.ts
|
|
106978
107944
|
/**
|
|
@@ -107047,29 +108013,6 @@ const newCommandId = Effect.gen(function* () {
|
|
|
107047
108013
|
const crypto = yield* Crypto.Crypto;
|
|
107048
108014
|
return CommandId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
|
|
107049
108015
|
});
|
|
107050
|
-
const fusionInvocationLine = /^(?:\/fusion|\$fusion)(?:\s+.*)?$/i;
|
|
107051
|
-
const fusionAffirmativeLine = /^(?:approved?|yes(?:,?\s+(?:please|do it))?|ok(?:ay)?|go ahead|do it|proceed)[.!]?$/i;
|
|
107052
|
-
function lastNonEmptyLine(text) {
|
|
107053
|
-
return text.split(/\r?\n/).findLast((line) => line.trim().length > 0)?.trim() ?? "";
|
|
107054
|
-
}
|
|
107055
|
-
function directlyInvokesFusion(text) {
|
|
107056
|
-
return text.split(/\r?\n/).some((line) => fusionInvocationLine.test(line.trim()));
|
|
107057
|
-
}
|
|
107058
|
-
function asksForFusionApproval(message) {
|
|
107059
|
-
if (message?.role !== "assistant") return false;
|
|
107060
|
-
const text = message.text.toLowerCase();
|
|
107061
|
-
return text.includes("fusion") && (text.includes("approve") || text.includes("approval"));
|
|
107062
|
-
}
|
|
107063
|
-
const requireFusionApproval = Effect.fn("mcp.threads.requireFusionApproval")(function* (threadId) {
|
|
107064
|
-
const thread = yield* (yield* ProjectionSnapshotQuery).getThreadDetailById(threadId).pipe(Effect.mapError(() => new ThreadPairApprovalRequiredError({ threadId })));
|
|
107065
|
-
if (Option.isNone(thread)) return yield* new ThreadPairApprovalRequiredError({ threadId });
|
|
107066
|
-
const latestUserIndex = thread.value.messages.findLastIndex((message) => message.role === "user");
|
|
107067
|
-
const latestUser = latestUserIndex >= 0 ? thread.value.messages[latestUserIndex] : void 0;
|
|
107068
|
-
if (latestUser !== void 0 && directlyInvokesFusion(latestUser.text)) return;
|
|
107069
|
-
const precedingAssistant = thread.value.messages.slice(0, latestUserIndex).findLast((message) => message.role === "assistant");
|
|
107070
|
-
if (latestUser !== void 0 && fusionAffirmativeLine.test(lastNonEmptyLine(latestUser.text)) && asksForFusionApproval(precedingAssistant)) return;
|
|
107071
|
-
return yield* new ThreadPairApprovalRequiredError({ threadId });
|
|
107072
|
-
});
|
|
107073
108016
|
/**
|
|
107074
108017
|
* The model a spawned thread starts on.
|
|
107075
108018
|
*
|
|
@@ -107087,6 +108030,42 @@ const resolveSpawnModelSelection = (requested, inherited) => requested === void
|
|
|
107087
108030
|
...requested.options !== void 0 ? { options: requested.options } : {}
|
|
107088
108031
|
};
|
|
107089
108032
|
const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
108033
|
+
thread_plan_update: (input) => Effect.gen(function* () {
|
|
108034
|
+
const { threadId } = yield* requireThreadCapability();
|
|
108035
|
+
const threads = yield* ProjectionThreadRepository;
|
|
108036
|
+
const reject = (detail) => new ThreadControlRejectedError({
|
|
108037
|
+
threadId,
|
|
108038
|
+
commandType: "thread.activity.append",
|
|
108039
|
+
detail
|
|
108040
|
+
});
|
|
108041
|
+
const thread = yield* threads.getById({ threadId }).pipe(Effect.mapError((cause) => reject(cause.message)));
|
|
108042
|
+
if (Option.isNone(thread)) return yield* reject("Current thread does not exist.");
|
|
108043
|
+
if (input.plan.filter((step) => step.status === "in_progress").length > 1) return yield* reject("At most one phase may be in progress.");
|
|
108044
|
+
const crypto = yield* Crypto.Crypto;
|
|
108045
|
+
const createdAt = DateTime.formatIso(yield* DateTime.now);
|
|
108046
|
+
yield* dispatchControl({
|
|
108047
|
+
type: "thread.activity.append",
|
|
108048
|
+
commandId: yield* newCommandId,
|
|
108049
|
+
threadId,
|
|
108050
|
+
createdAt,
|
|
108051
|
+
activity: {
|
|
108052
|
+
id: EventId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie)),
|
|
108053
|
+
createdAt,
|
|
108054
|
+
tone: "info",
|
|
108055
|
+
kind: "turn.plan.updated",
|
|
108056
|
+
summary: "Plan updated",
|
|
108057
|
+
turnId: thread.value.latestTurnId,
|
|
108058
|
+
payload: {
|
|
108059
|
+
...input,
|
|
108060
|
+
plan: input.plan.map((step) => ({
|
|
108061
|
+
step: step.step,
|
|
108062
|
+
status: step.status === "in_progress" ? "inProgress" : step.status
|
|
108063
|
+
}))
|
|
108064
|
+
}
|
|
108065
|
+
}
|
|
108066
|
+
}, threadId);
|
|
108067
|
+
return { threadId };
|
|
108068
|
+
}),
|
|
107090
108069
|
ask_user_question: (input) => Effect.gen(function* () {
|
|
107091
108070
|
const invocation = yield* requireThreadCapability();
|
|
107092
108071
|
const crypto = yield* Crypto.Crypto;
|
|
@@ -107158,8 +108137,11 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
107158
108137
|
}).pipe(Effect.ensuring(Effect.sync(() => forgetPendingMcpUserInput(invocation.threadId, requestId))));
|
|
107159
108138
|
}),
|
|
107160
108139
|
thread_spawn: (input) => Effect.gen(function* () {
|
|
107161
|
-
const invocation = yield* requireThreadSpawn();
|
|
107162
|
-
if (input.fusionWatcher === true) yield*
|
|
108140
|
+
const invocation = yield* requireThreadSpawn(input.fusion === true);
|
|
108141
|
+
if (input.fusion === true && input.fusionWatcher === true) return yield* new ThreadSpawnNotPermittedError({
|
|
108142
|
+
threadId: invocation.threadId,
|
|
108143
|
+
detail: "Choose a new Fusion pair or a standalone watcher, not both."
|
|
108144
|
+
});
|
|
107163
108145
|
const registry = yield* McpSessionRegistry;
|
|
107164
108146
|
const threads = yield* ProjectionThreadRepository;
|
|
107165
108147
|
const crypto = yield* Crypto.Crypto;
|
|
@@ -107173,7 +108155,11 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
107173
108155
|
});
|
|
107174
108156
|
const template = parent.value;
|
|
107175
108157
|
const projectId = input.projectId ?? template.projectId;
|
|
107176
|
-
const
|
|
108158
|
+
const settings = input.fusion === true || input.fusionWatcher === true ? yield* (yield* ServerSettingsService).getSettings.pipe(Effect.mapError((cause) => new ThreadSpawnNotPermittedError({
|
|
108159
|
+
threadId: invocation.threadId,
|
|
108160
|
+
detail: `Fusion settings could not be read: ${cause.message}`
|
|
108161
|
+
}))) : void 0;
|
|
108162
|
+
const modelSelection = resolveSpawnModelSelection(input.modelSelection, (input.fusionWatcher === true ? settings?.fusionWatcherModelSelection : settings?.fusionBuilderModelSelection) ?? template.modelSelection);
|
|
107177
108163
|
const runtimeMode = input.runtimeMode ?? template.runtimeMode;
|
|
107178
108164
|
const interactionMode = input.interactionMode ?? template.interactionMode;
|
|
107179
108165
|
const compressMode = input.compressMode ?? template.compressMode;
|
|
@@ -107197,8 +108183,42 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
107197
108183
|
}, threadId);
|
|
107198
108184
|
yield* registry.recordSpawnedThread({
|
|
107199
108185
|
providerSessionId: invocation.providerSessionId,
|
|
107200
|
-
threadId
|
|
108186
|
+
threadId,
|
|
108187
|
+
...input.fusionWatcher === true ? { mayCreateFusionPairs: true } : {}
|
|
107201
108188
|
});
|
|
108189
|
+
const fusionPair = input.fusion === true ? {
|
|
108190
|
+
pairId: ThreadPairId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie)),
|
|
108191
|
+
watcherThreadId: ThreadId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie))
|
|
108192
|
+
} : void 0;
|
|
108193
|
+
if (fusionPair !== void 0) {
|
|
108194
|
+
yield* dispatchControl({
|
|
108195
|
+
type: "thread.create",
|
|
108196
|
+
commandId: yield* newCommandId,
|
|
108197
|
+
threadId: fusionPair.watcherThreadId,
|
|
108198
|
+
projectId,
|
|
108199
|
+
title: `Review: ${input.title}`,
|
|
108200
|
+
modelSelection: settings?.fusionWatcherModelSelection ?? modelSelection,
|
|
108201
|
+
runtimeMode,
|
|
108202
|
+
interactionMode: "default",
|
|
108203
|
+
compressMode,
|
|
108204
|
+
unpromptedSubagents,
|
|
108205
|
+
branch: null,
|
|
108206
|
+
worktreePath: null,
|
|
108207
|
+
createdAt
|
|
108208
|
+
}, fusionPair.watcherThreadId);
|
|
108209
|
+
yield* registry.recordSpawnedThread({
|
|
108210
|
+
providerSessionId: invocation.providerSessionId,
|
|
108211
|
+
threadId: fusionPair.watcherThreadId
|
|
108212
|
+
});
|
|
108213
|
+
yield* dispatchControl({
|
|
108214
|
+
type: "thread-pair.create",
|
|
108215
|
+
commandId: yield* newCommandId,
|
|
108216
|
+
pairId: fusionPair.pairId,
|
|
108217
|
+
implementerThreadId: threadId,
|
|
108218
|
+
watcherThreadId: fusionPair.watcherThreadId,
|
|
108219
|
+
createdAt
|
|
108220
|
+
}, threadId);
|
|
108221
|
+
}
|
|
107202
108222
|
yield* dispatchControl({
|
|
107203
108223
|
type: "thread.turn.start",
|
|
107204
108224
|
commandId: yield* newCommandId,
|
|
@@ -107220,12 +108240,12 @@ const ThreadToolkitHandlersLive = ThreadToolkit.toLayer({
|
|
|
107220
108240
|
return {
|
|
107221
108241
|
threadId,
|
|
107222
108242
|
projectId,
|
|
107223
|
-
title: input.title
|
|
108243
|
+
title: input.title,
|
|
108244
|
+
...fusionPair
|
|
107224
108245
|
};
|
|
107225
108246
|
}),
|
|
107226
108247
|
thread_pair_create: (input) => Effect.gen(function* () {
|
|
107227
108248
|
const { invocation, threadId: watcherThreadId } = yield* requireThreadControlTarget(input.watcherThreadId);
|
|
107228
|
-
yield* requireFusionApproval(invocation.threadId);
|
|
107229
108249
|
const crypto = yield* Crypto.Crypto;
|
|
107230
108250
|
const pairId = ThreadPairId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
|
|
107231
108251
|
const continuationMessageId = MessageId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
|
|
@@ -107763,24 +108783,40 @@ const ThreadWatchEventsTool = Tool.make("thread_watch_events", {
|
|
|
107763
108783
|
failure: ThreadWatchToolError,
|
|
107764
108784
|
dependencies: [McpInvocationContext, ThreadEventStreamService]
|
|
107765
108785
|
}).annotate(Tool.Title, "Read watched thread events").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
|
|
107766
|
-
const
|
|
107767
|
-
|
|
107768
|
-
|
|
107769
|
-
|
|
107770
|
-
|
|
107771
|
-
|
|
107772
|
-
|
|
107773
|
-
|
|
107774
|
-
|
|
107775
|
-
|
|
107776
|
-
|
|
107777
|
-
|
|
107778
|
-
|
|
107779
|
-
|
|
107780
|
-
|
|
107781
|
-
|
|
107782
|
-
|
|
107783
|
-
|
|
108786
|
+
const ThreadWatchReviewTool = Tool.make("thread_watch_review", {
|
|
108787
|
+
description: "Read bounded compact review evidence for an explicitly granted thread. Combines assistant fragments by message identity; preserves user requirements, tool evidence, plans, errors and turn boundaries. Resume with nextAfterSequence and the same throughSequence until hasMore is false, even on empty pages. Message operations append or replace by identity across pages. Truncated evidence includes source sequence ranges for targeted recovery with thread_watch_events; do not treat an excerpt as full proof.",
|
|
108788
|
+
parameters: ThreadWatchReviewInput,
|
|
108789
|
+
success: ThreadWatchReviewResult,
|
|
108790
|
+
failure: ThreadWatchToolError,
|
|
108791
|
+
dependencies: [McpInvocationContext, ThreadEventStreamService]
|
|
108792
|
+
}).annotate(Tool.Title, "Read compact thread review").annotate(Tool.Readonly, true).annotate(Tool.Destructive, false).annotate(Tool.Idempotent, true);
|
|
108793
|
+
const WatchToolkit = Toolkit.make(ThreadWatchEventsTool, ThreadWatchReviewTool);
|
|
108794
|
+
const WatchToolkitHandlersLive = WatchToolkit.toLayer({
|
|
108795
|
+
thread_watch_review: (input) => Effect.gen(function* () {
|
|
108796
|
+
yield* requireWatchCapability(input.threadId);
|
|
108797
|
+
return yield* (yield* ThreadEventStreamService).readReview(input).pipe(Effect.mapError((cause) => new ThreadWatchFailedError({
|
|
108798
|
+
threadId: input.threadId,
|
|
108799
|
+
detail: cause.message
|
|
108800
|
+
})));
|
|
108801
|
+
}),
|
|
108802
|
+
thread_watch_events: (input) => Effect.gen(function* () {
|
|
108803
|
+
yield* requireWatchCapability(input.threadId);
|
|
108804
|
+
const page = yield* (yield* ThreadEventStreamService).read({
|
|
108805
|
+
threadId: input.threadId,
|
|
108806
|
+
...input.afterSequence !== void 0 ? { afterSequence: input.afterSequence } : {},
|
|
108807
|
+
limit: input.limit ?? 50
|
|
108808
|
+
}).pipe(Effect.mapError((cause) => new ThreadWatchFailedError({
|
|
108809
|
+
threadId: input.threadId,
|
|
108810
|
+
detail: cause.message
|
|
108811
|
+
})));
|
|
108812
|
+
return {
|
|
108813
|
+
threadId: input.threadId,
|
|
108814
|
+
events: page.events,
|
|
108815
|
+
headSequence: page.headSequence,
|
|
108816
|
+
hasMore: page.hasMore
|
|
108817
|
+
};
|
|
108818
|
+
})
|
|
108819
|
+
});
|
|
107784
108820
|
//#endregion
|
|
107785
108821
|
//#region src/mcp/McpHttpServer.ts
|
|
107786
108822
|
const unauthorized = HttpServerResponse.jsonUnsafe({
|
|
@@ -107955,6 +108991,100 @@ var ThreadDeletionReactor = class extends Context.Service()("@p4code/cli/orchest
|
|
|
107955
108991
|
//#region src/orchestration/Services/FusionWatcherReactor.ts
|
|
107956
108992
|
var FusionWatcherReactor = class extends Context.Service()("@p4code/cli/orchestration/Services/FusionWatcherReactor") {};
|
|
107957
108993
|
//#endregion
|
|
108994
|
+
//#region src/orchestration/Layers/ThreadCompletionReactor.ts
|
|
108995
|
+
const COMPLETION_SWEEP_BATCH_SIZE = 25;
|
|
108996
|
+
const COMPLETION_SWEEP_INTERVAL = Duration.minutes(1);
|
|
108997
|
+
const COMPLETION_PR_TIMEOUT = Duration.seconds(10);
|
|
108998
|
+
const MILLISECONDS_PER_DAY = 1440 * 60 * 1e3;
|
|
108999
|
+
const make$6 = Effect.gen(function* () {
|
|
109000
|
+
const sql = yield* SqlClient.SqlClient;
|
|
109001
|
+
const settings = yield* ServerSettingsService;
|
|
109002
|
+
const git = yield* GitManager;
|
|
109003
|
+
const engine = yield* OrchestrationEngineService;
|
|
109004
|
+
const crypto = yield* Crypto.Crypto;
|
|
109005
|
+
const mutex = yield* Semaphore.make(1);
|
|
109006
|
+
let cursor = "";
|
|
109007
|
+
const candidates = SqlSchema.findAll({
|
|
109008
|
+
Request: Schema$1.String,
|
|
109009
|
+
Result: Schema$1.Struct({
|
|
109010
|
+
threadId: ThreadId,
|
|
109011
|
+
cwd: Schema$1.String,
|
|
109012
|
+
branch: Schema$1.NullOr(Schema$1.String),
|
|
109013
|
+
lastEngagedAt: IsoDateTime,
|
|
109014
|
+
pinnedAt: Schema$1.NullOr(IsoDateTime),
|
|
109015
|
+
projectDeletedAt: Schema$1.NullOr(IsoDateTime),
|
|
109016
|
+
pendingApprovalCount: Schema$1.Number,
|
|
109017
|
+
pendingUserInputCount: Schema$1.Number,
|
|
109018
|
+
sessionStatus: Schema$1.NullOr(Schema$1.String)
|
|
109019
|
+
}),
|
|
109020
|
+
execute: (afterThreadId) => sql`
|
|
109021
|
+
SELECT t.thread_id AS "threadId", COALESCE(t.worktree_path, p.workspace_root) AS "cwd",
|
|
109022
|
+
t.branch, t.last_engaged_at AS "lastEngagedAt", t.pinned_at AS "pinnedAt",
|
|
109023
|
+
p.deleted_at AS "projectDeletedAt", t.pending_approval_count AS "pendingApprovalCount",
|
|
109024
|
+
t.pending_user_input_count AS "pendingUserInputCount", s.status AS "sessionStatus"
|
|
109025
|
+
FROM projection_threads t
|
|
109026
|
+
JOIN projection_projects p ON p.project_id = t.project_id
|
|
109027
|
+
LEFT JOIN projection_thread_sessions s ON s.thread_id = t.thread_id
|
|
109028
|
+
WHERE t.lifecycle = 'active' AND t.deleted_at IS NULL
|
|
109029
|
+
AND t.thread_id > ${afterThreadId}
|
|
109030
|
+
ORDER BY t.thread_id ASC LIMIT ${COMPLETION_SWEEP_BATCH_SIZE}
|
|
109031
|
+
`
|
|
109032
|
+
});
|
|
109033
|
+
const sweep = Effect.fn("ThreadCompletionReactor.sweep")(function* () {
|
|
109034
|
+
yield* mutex.withPermits(1)(Effect.gen(function* () {
|
|
109035
|
+
const now = yield* Clock.currentTimeMillis;
|
|
109036
|
+
const days = (yield* settings.getSettings).threadAutoCompleteAfterDays;
|
|
109037
|
+
const cutoff = days === null ? null : now - days * MILLISECONDS_PER_DAY;
|
|
109038
|
+
const rows = yield* candidates(cursor);
|
|
109039
|
+
const branchStates = /* @__PURE__ */ new Map();
|
|
109040
|
+
for (const row of rows) {
|
|
109041
|
+
if (row.projectDeletedAt !== null || row.pinnedAt !== null || row.pendingApprovalCount > 0 || row.pendingUserInputCount > 0 || row.sessionStatus === "starting" || row.sessionStatus === "running") continue;
|
|
109042
|
+
const key = `${row.cwd.length}:${row.cwd}${row.branch ?? ""}`;
|
|
109043
|
+
let pr = branchStates.get(key);
|
|
109044
|
+
if (pr === void 0) {
|
|
109045
|
+
pr = yield* git.threadCompletionPrState({
|
|
109046
|
+
cwd: row.cwd,
|
|
109047
|
+
branch: row.branch
|
|
109048
|
+
}).pipe(Effect.timeout(COMPLETION_PR_TIMEOUT), Effect.orElseSucceed(() => ({ state: "unknown" })));
|
|
109049
|
+
branchStates.set(key, pr);
|
|
109050
|
+
}
|
|
109051
|
+
if (pr.state === "unknown" || pr.state === "open") continue;
|
|
109052
|
+
const engagedAt = Date.parse(row.lastEngagedAt);
|
|
109053
|
+
const terminalAt = pr.state === "terminal" ? Date.parse(pr.terminalAt) : null;
|
|
109054
|
+
if (terminalAt !== null && (!Number.isFinite(terminalAt) || terminalAt > now)) continue;
|
|
109055
|
+
const eligible = terminalAt !== null && terminalAt > engagedAt ? {
|
|
109056
|
+
reason: "pull-request",
|
|
109057
|
+
eligibleAt: DateTime.formatIso(DateTime.makeUnsafe(terminalAt))
|
|
109058
|
+
} : cutoff !== null && engagedAt < cutoff ? {
|
|
109059
|
+
reason: "inactivity",
|
|
109060
|
+
eligibleAt: DateTime.formatIso(DateTime.makeUnsafe(cutoff))
|
|
109061
|
+
} : null;
|
|
109062
|
+
if (eligible === null) continue;
|
|
109063
|
+
const commandId = CommandId.make(`server:thread-complete:${yield* crypto.randomUUIDv4}`);
|
|
109064
|
+
yield* engine.dispatch({
|
|
109065
|
+
type: "thread.complete.auto",
|
|
109066
|
+
commandId,
|
|
109067
|
+
threadId: row.threadId,
|
|
109068
|
+
expectedLastEngagedAt: row.lastEngagedAt,
|
|
109069
|
+
...eligible
|
|
109070
|
+
}).pipe(Effect.catch((cause) => Effect.logDebug("Automatic completion did not apply", {
|
|
109071
|
+
threadId: row.threadId,
|
|
109072
|
+
cause
|
|
109073
|
+
})));
|
|
109074
|
+
}
|
|
109075
|
+
cursor = rows.length < COMPLETION_SWEEP_BATCH_SIZE ? "" : rows.at(-1).threadId;
|
|
109076
|
+
}));
|
|
109077
|
+
});
|
|
109078
|
+
return {
|
|
109079
|
+
sweep,
|
|
109080
|
+
start: Effect.fn("ThreadCompletionReactor.start")(function* () {
|
|
109081
|
+
yield* sweep().pipe(Effect.catchCause((cause) => Effect.logWarning("Thread completion sweep failed", { cause })), Effect.repeat(Schedule.spaced(COMPLETION_SWEEP_INTERVAL)), Effect.forkScoped);
|
|
109082
|
+
})
|
|
109083
|
+
};
|
|
109084
|
+
});
|
|
109085
|
+
var ThreadCompletionReactor = class extends Context.Service()("@p4code/cli/orchestration/Layers/ThreadCompletionReactor") {};
|
|
109086
|
+
const ThreadCompletionReactorLive = Layer.effect(ThreadCompletionReactor, make$6);
|
|
109087
|
+
//#endregion
|
|
107958
109088
|
//#region src/orchestration/Services/ScheduledTaskReactor.ts
|
|
107959
109089
|
/**
|
|
107960
109090
|
* ScheduledTaskReactor - fires user-created scheduled tasks.
|
|
@@ -107975,6 +109105,7 @@ const makeOrchestrationReactor = Effect.gen(function* () {
|
|
|
107975
109105
|
const threadDeletionReactor = yield* ThreadDeletionReactor;
|
|
107976
109106
|
const fusionWatcherReactor = yield* FusionWatcherReactor;
|
|
107977
109107
|
const scheduledTaskReactor = yield* ScheduledTaskReactor;
|
|
109108
|
+
const completionReactor = yield* ThreadCompletionReactor;
|
|
107978
109109
|
return { start: Effect.fn("start")(function* () {
|
|
107979
109110
|
yield* providerRuntimeIngestion.start();
|
|
107980
109111
|
yield* providerCommandReactor.start();
|
|
@@ -107982,6 +109113,7 @@ const makeOrchestrationReactor = Effect.gen(function* () {
|
|
|
107982
109113
|
yield* threadDeletionReactor.start();
|
|
107983
109114
|
yield* fusionWatcherReactor.start();
|
|
107984
109115
|
yield* scheduledTaskReactor.start();
|
|
109116
|
+
yield* completionReactor.start();
|
|
107985
109117
|
}) };
|
|
107986
109118
|
});
|
|
107987
109119
|
const OrchestrationReactorLive = Layer.effect(OrchestrationReactor, makeOrchestrationReactor);
|
|
@@ -109375,7 +110507,7 @@ const HANDLED_TURN_START_KEY_TTL = Duration.minutes(30);
|
|
|
109375
110507
|
const DEFAULT_RUNTIME_MODE = "full-access";
|
|
109376
110508
|
const DEFAULT_THREAD_TITLE = "New thread";
|
|
109377
110509
|
const NON_SYSTEM_PROVIDER_STRUCTURED_USER_QUESTIONS = structuredUserQuestionPrompt("your provider's structured user-input question tool");
|
|
109378
|
-
const FUSION_PROMOTION_INSTRUCTIONS = `Work independently in this normal thread. Fusion is a silent escalation path, not a startup procedure. Do not inspect Fusion tools/skill, mention Fusion status, or announce that Fusion was not invoked. First analyze the task normally. Only if that analysis reveals a concrete unresolved tradeoff, correctness risk, or design decision materially needing a second opinion, stop before implementation, propose Fusion, and ask the user for explicit approval. The user may approve with ordinary affirmative text such as "approved"
|
|
110510
|
+
const FUSION_PROMOTION_INSTRUCTIONS = `Work independently in this normal thread. Fusion is a silent escalation path, not a startup procedure. Do not inspect Fusion tools/skill, mention Fusion status, or announce that Fusion was not invoked. First analyze the task normally. Only if that analysis reveals a concrete unresolved tradeoff, correctness risk, or design decision materially needing a second opinion, stop before implementation, propose Fusion, and ask the user for explicit approval. The user may approve with ordinary affirmative text such as "approved". A direct user request to use or spawn Fusion authorizes Fusion directly without a prior proposal; /fusion and $fusion are optional shortcuts. Do not activate, spawn, or promote until one of those authorizations arrives. UI work, complex logic, task size, unfamiliarity, or duration alone never qualifies.`;
|
|
109379
110511
|
const isFusionWatcherWakeMessageId = (messageId) => messageId.startsWith("fusion-review:") || messageId.startsWith("fusion-gate:");
|
|
109380
110512
|
const findActiveFusionPair = (pairs, threadId) => (pairs ?? []).find((pair) => pair.detachedAt === null && (pair.implementerThreadId === threadId || pair.watcherThreadId === threadId));
|
|
109381
110513
|
const fusionRoleForThread = (pairs, threadId) => {
|
|
@@ -110981,7 +112113,7 @@ After restart/context loss, derive phase from workspace git log/status, PR, rece
|
|
|
110981
112113
|
const watcherPrompt = (input) => `${FUSION_REVIEW_PROMPT_PREFIX}
|
|
110982
112114
|
Review completed builder turn ${input.implementerThreadId}.
|
|
110983
112115
|
|
|
110984
|
-
Call
|
|
112116
|
+
Call thread_watch_review, threadId ${input.implementerThreadId}, afterSequence ${input.afterSequence}, throughSequence ${input.throughSequence}. Continue with nextAfterSequence and the same throughSequence until hasMore is false, including empty pages. Apply message append/replace operations by identity across pages. Recover truncated or uncertain evidence with targeted thread_watch_events reads using its source sequence range. Inspect repo when useful.
|
|
110985
112117
|
|
|
110986
112118
|
Always report concise:
|
|
110987
112119
|
|
|
@@ -110993,7 +112125,7 @@ Determine review boundary from builder's todo status:
|
|
|
110993
112125
|
|
|
110994
112126
|
- Remaining phases, or final status unclear, and the builder has actionable work: intermediate phase review. Call thread_advise for ${input.implementerThreadId}. With objections, send required corrections and next phase. With none, explicitly approve phase and tell builder to continue next todo phase. Never require tests, typecheck, lint, or builds before the final phase.
|
|
110995
112127
|
- Builder waiting on an external process or with nothing actionable: no thread_advise. Report the state here and end.
|
|
110996
|
-
- Final whole-task phase ready:
|
|
112128
|
+
- Final whole-task phase ready: combine previously reviewed evidence with this delta and inspect the full task diff/state. Review original requirements and later corrections, integration across all phases, verification, and delivery. Recover missing requirements or uncertain prior evidence with targeted compact history reads bounded by throughSequence ${input.throughSequence}, and raw source reads when necessary. Do not replay raw history from zero by default. If prior context is unavailable, recover the requirements before concluding. Advise only for concrete objections or unfinished work; otherwise report no objections and end.
|
|
110997
112129
|
|
|
110998
112130
|
${watcherPowers(input.implementerThreadId)}
|
|
110999
112131
|
|
|
@@ -111012,7 +112144,7 @@ const gateKindDescription = (gate) => {
|
|
|
111012
112144
|
const gatePrompt = (input) => `${FUSION_GATE_PROMPT_PREFIX}
|
|
111013
112145
|
Gate ${input.gate.id} is open on builder thread ${input.implementerThreadId}: ${gateKindDescription(input.gate)}. Round ${Math.min(input.gate.round + 1, input.roundCap)} of ${input.roundCap}.
|
|
111014
112146
|
|
|
111015
|
-
First read delta:
|
|
112147
|
+
First read delta: thread_watch_review, threadId ${input.implementerThreadId}, afterSequence ${input.afterSequence}, throughSequence ${input.throughSequence}. Continue with nextAfterSequence and the same throughSequence until hasMore is false, including empty pages. Apply message append/replace operations by identity across pages; recover truncated or uncertain evidence with targeted thread_watch_events reads using its source sequence range. Inspect repo when useful.
|
|
111016
112148
|
|
|
111017
112149
|
Then thread_gate_respond, threadId ${input.implementerThreadId}, gateId ${input.gate.id}:
|
|
111018
112150
|
|
|
@@ -112745,7 +113877,7 @@ const PlatformServicesLive = Layer.unwrap(Effect.gen(function* () {
|
|
|
112745
113877
|
return layer;
|
|
112746
113878
|
}
|
|
112747
113879
|
}));
|
|
112748
|
-
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(RuntimeReceiptBusLive));
|
|
113880
|
+
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(RuntimeReceiptBusLive));
|
|
112749
113881
|
const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$4));
|
|
112750
113882
|
const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
|
|
112751
113883
|
const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
|