@p4code/cli 0.2.9 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/bin.mjs CHANGED
@@ -125,7 +125,7 @@ const closeServer = (server) => {
125
125
  * NetService - Service tag for startup networking helpers.
126
126
  */
127
127
  var NetService = class extends Context.Service()("@p4code/shared/Net/NetService") {};
128
- const make$88 = () => {
128
+ const make$89 = () => {
129
129
  /**
130
130
  * Returns true when a TCP server can bind to {host, port}.
131
131
  * `EADDRNOTAVAIL` is treated as available so IPv6-absent hosts don't fail
@@ -234,10 +234,10 @@ const make$88 = () => {
234
234
  })
235
235
  };
236
236
  };
237
- const layer$79 = Layer.sync(NetService, make$88);
237
+ const layer$80 = Layer.sync(NetService, make$89);
238
238
  //#endregion
239
239
  //#region package.json
240
- var version = "0.2.9";
240
+ var version = "0.2.10";
241
241
  //#endregion
242
242
  //#region src/config.ts
243
243
  /**
@@ -258,8 +258,8 @@ var ServerConfig$1 = class extends Context.Service()("@p4code/cli/config/ServerC
258
258
  /** @deprecated Import and use `layerTest` from this module. */
259
259
  static layerTest = (cwd, baseDirOrPrefix) => layerTest$3(cwd, baseDirOrPrefix);
260
260
  };
261
- const make$87 = (config) => ServerConfig$1.of(config);
262
- const layer$78 = (config) => Layer.succeed(ServerConfig$1, make$87(config));
261
+ const make$88 = (config) => ServerConfig$1.of(config);
262
+ const layer$79 = (config) => Layer.succeed(ServerConfig$1, make$88(config));
263
263
  const deriveServerPaths = Effect.fn(function* (baseDir, devUrl, options = {}) {
264
264
  const { join } = yield* Path.Path;
265
265
  const stateDir = join(baseDir, devUrl !== void 0 && !options.baseDirIsExplicit ? "dev" : "userdata");
@@ -10625,6 +10625,116 @@ var UsageReadError = class extends Schema$1.TaggedErrorClass()("UsageReadError",
10625
10625
  }
10626
10626
  };
10627
10627
  //#endregion
10628
+ //#region ../../packages/contracts/src/feed.ts
10629
+ const FeedSourceId = Schema$1.String.pipe(Schema$1.brand("FeedSourceId"));
10630
+ const FeedArticleId = Schema$1.String.pipe(Schema$1.brand("FeedArticleId"));
10631
+ const FeedSourceKind = Schema$1.Literals(["hacker_news", "syndication"]);
10632
+ const FeedArticleStatus = Schema$1.Literals([
10633
+ "pending_summary",
10634
+ "ready",
10635
+ "summary_unavailable",
10636
+ "summary_failed"
10637
+ ]);
10638
+ const FeedEngagementBand = Schema$1.Literals([
10639
+ "unknown",
10640
+ "low",
10641
+ "medium",
10642
+ "high"
10643
+ ]);
10644
+ var FeedSource = class extends Schema$1.Class("FeedSource")({
10645
+ id: FeedSourceId,
10646
+ name: Schema$1.String,
10647
+ kind: FeedSourceKind,
10648
+ feedUrl: Schema$1.String,
10649
+ siteUrl: Schema$1.String,
10650
+ enabled: Schema$1.Boolean,
10651
+ createdAt: Schema$1.String,
10652
+ updatedAt: Schema$1.String
10653
+ }) {};
10654
+ var FeedEngagement = class extends Schema$1.Class("FeedEngagement")({
10655
+ articleId: FeedArticleId,
10656
+ points: Schema$1.NullOr(Schema$1.Number),
10657
+ comments: Schema$1.NullOr(Schema$1.Number),
10658
+ band: FeedEngagementBand,
10659
+ observedAt: Schema$1.String
10660
+ }) {};
10661
+ var FeedSummary = class extends Schema$1.Class("FeedSummary")({
10662
+ articleId: FeedArticleId,
10663
+ modelSelection: Schema$1.String,
10664
+ summary: Schema$1.String,
10665
+ highlights: Schema$1.Array(Schema$1.String),
10666
+ references: Schema$1.Array(Schema$1.String),
10667
+ summarizedAt: Schema$1.String
10668
+ }) {};
10669
+ var FeedArticle = class extends Schema$1.Class("FeedArticle")({
10670
+ id: FeedArticleId,
10671
+ sourceId: FeedSourceId,
10672
+ sourceName: Schema$1.String,
10673
+ canonicalUrl: Schema$1.String,
10674
+ discussionUrl: Schema$1.NullOr(Schema$1.String),
10675
+ title: Schema$1.String,
10676
+ author: Schema$1.NullOr(Schema$1.String),
10677
+ publishedAt: Schema$1.String,
10678
+ fetchedAt: Schema$1.String,
10679
+ contentText: Schema$1.NullOr(Schema$1.String),
10680
+ status: FeedArticleStatus,
10681
+ summary: Schema$1.NullOr(FeedSummary),
10682
+ engagement: FeedEngagement,
10683
+ readAt: Schema$1.NullOr(Schema$1.String)
10684
+ }) {};
10685
+ var FeedListInput = class extends Schema$1.Class("FeedListInput")({
10686
+ query: Schema$1.optional(Schema$1.String),
10687
+ sourceId: Schema$1.optional(FeedSourceId),
10688
+ unreadOnly: Schema$1.optional(Schema$1.Boolean),
10689
+ startDate: Schema$1.optional(Schema$1.String),
10690
+ endDate: Schema$1.optional(Schema$1.String),
10691
+ sort: Schema$1.optional(Schema$1.Literals(["newest", "oldest"]))
10692
+ }) {};
10693
+ var FeedListResult = class extends Schema$1.Class("FeedListResult")({
10694
+ articles: Schema$1.Array(FeedArticle),
10695
+ refreshedAt: Schema$1.NullOr(Schema$1.String)
10696
+ }) {};
10697
+ var FeedSourceUpsertInput = class extends Schema$1.Class("FeedSourceUpsertInput")({
10698
+ id: Schema$1.optional(FeedSourceId),
10699
+ name: Schema$1.String,
10700
+ kind: FeedSourceKind,
10701
+ feedUrl: Schema$1.String,
10702
+ siteUrl: Schema$1.String,
10703
+ enabled: Schema$1.Boolean
10704
+ }) {};
10705
+ var FeedSourceIdInput = class extends Schema$1.Class("FeedSourceIdInput")({ sourceId: FeedSourceId }) {};
10706
+ var FeedMarkReadInput = class extends Schema$1.Class("FeedMarkReadInput")({
10707
+ articleId: FeedArticleId,
10708
+ read: Schema$1.Boolean
10709
+ }) {};
10710
+ var FeedCleanupInput = class extends Schema$1.Class("FeedCleanupInput")({
10711
+ startDate: Schema$1.String,
10712
+ endDate: Schema$1.String,
10713
+ confirm: Schema$1.Boolean
10714
+ }) {};
10715
+ var FeedCleanupResult = class extends Schema$1.Class("FeedCleanupResult")({
10716
+ count: Schema$1.Number,
10717
+ deleted: Schema$1.Boolean
10718
+ }) {};
10719
+ var FeedRefreshResult = class extends Schema$1.Class("FeedRefreshResult")({
10720
+ fetched: Schema$1.Number,
10721
+ summarized: Schema$1.Number,
10722
+ failedSources: Schema$1.Array(Schema$1.String),
10723
+ refreshedAt: Schema$1.String
10724
+ }) {};
10725
+ var FeedError = class extends Schema$1.TaggedErrorClass()("FeedError", {
10726
+ code: Schema$1.Literals([
10727
+ "hub_unavailable",
10728
+ "invalid_feed",
10729
+ "fetch_failed",
10730
+ "article_unreadable",
10731
+ "luna_unavailable",
10732
+ "summarization_failed"
10733
+ ]),
10734
+ message: Schema$1.String
10735
+ }) {};
10736
+ const FeedSourceList = Schema$1.Array(FeedSource);
10737
+ //#endregion
10628
10738
  //#region ../../packages/contracts/src/rpc.ts
10629
10739
  const WS_METHODS = {
10630
10740
  projectsList: "projects.list",
@@ -10704,6 +10814,13 @@ const WS_METHODS = {
10704
10814
  tasksUpdate: "tasks.update",
10705
10815
  tasksDelete: "tasks.delete",
10706
10816
  tasksStartThread: "tasks.startThread",
10817
+ feedList: "feed.list",
10818
+ feedRefresh: "feed.refresh",
10819
+ feedSourcesList: "feed.sources.list",
10820
+ feedSourcesUpsert: "feed.sources.upsert",
10821
+ feedSourcesDelete: "feed.sources.delete",
10822
+ feedMarkRead: "feed.markRead",
10823
+ feedCleanup: "feed.cleanup",
10707
10824
  hubGetSyncStatus: "hub.getSyncStatus",
10708
10825
  hubConnect: "hub.connect",
10709
10826
  hubDisconnect: "hub.disconnect",
@@ -10810,6 +10927,42 @@ const WsTasksDeleteRpc = Rpc.make(WS_METHODS.tasksDelete, {
10810
10927
  success: Schema$1.Struct({}),
10811
10928
  error: TaskRpcError
10812
10929
  });
10930
+ const FeedRpcError = Schema$1.Union([FeedError, EnvironmentAuthorizationError]);
10931
+ const WsFeedListRpc = Rpc.make(WS_METHODS.feedList, {
10932
+ payload: FeedListInput,
10933
+ success: FeedListResult,
10934
+ error: FeedRpcError
10935
+ });
10936
+ const WsFeedRefreshRpc = Rpc.make(WS_METHODS.feedRefresh, {
10937
+ payload: Schema$1.Struct({}),
10938
+ success: FeedRefreshResult,
10939
+ error: FeedRpcError
10940
+ });
10941
+ const WsFeedSourcesListRpc = Rpc.make(WS_METHODS.feedSourcesList, {
10942
+ payload: Schema$1.Struct({}),
10943
+ success: FeedSourceList,
10944
+ error: FeedRpcError
10945
+ });
10946
+ const WsFeedSourcesUpsertRpc = Rpc.make(WS_METHODS.feedSourcesUpsert, {
10947
+ payload: FeedSourceUpsertInput,
10948
+ success: FeedSource,
10949
+ error: FeedRpcError
10950
+ });
10951
+ const WsFeedSourcesDeleteRpc = Rpc.make(WS_METHODS.feedSourcesDelete, {
10952
+ payload: FeedSourceIdInput,
10953
+ success: Schema$1.Struct({}),
10954
+ error: FeedRpcError
10955
+ });
10956
+ const WsFeedMarkReadRpc = Rpc.make(WS_METHODS.feedMarkRead, {
10957
+ payload: FeedMarkReadInput,
10958
+ success: Schema$1.Struct({}),
10959
+ error: FeedRpcError
10960
+ });
10961
+ const WsFeedCleanupRpc = Rpc.make(WS_METHODS.feedCleanup, {
10962
+ payload: FeedCleanupInput,
10963
+ success: FeedCleanupResult,
10964
+ error: FeedRpcError
10965
+ });
10813
10966
  /**
10814
10967
  * Start an agent on a task.
10815
10968
  *
@@ -11548,7 +11701,7 @@ const WsSubscribeAuthAccessRpc = Rpc.make(WS_METHODS.subscribeAuthAccess, {
11548
11701
  error: Schema$1.Union([AuthAccessStreamError, EnvironmentAuthorizationError]),
11549
11702
  stream: true
11550
11703
  });
11551
- const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, 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, 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);
11704
+ const WsRpcGroup = RpcGroup.make(WsServerProbeRpc, WsServerGetConfigRpc, WsServerRefreshProvidersRpc, WsServerUpdateProviderRpc, WsServerUpdateServerRpc, WsServerUpsertKeybindingRpc, WsServerRemoveKeybindingRpc, WsServerGetSettingsRpc, WsServerUpdateSettingsRpc, WsServerDiscoverSourceControlRpc, WsServerGetProviderUsageRpc, 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);
11552
11705
  //#endregion
11553
11706
  //#region ../../packages/shared/src/oauthScope.ts
11554
11707
  const OAUTH_SCOPE_TOKEN = /^[\u0021\u0023-\u005b\u005d-\u007e]+$/u;
@@ -11694,7 +11847,7 @@ function deriveAuthClientMetadata(input) {
11694
11847
  //#endregion
11695
11848
  //#region src/auth/EnvironmentAuthPolicy.ts
11696
11849
  var EnvironmentAuthPolicy = class extends Context.Service()("@p4code/cli/auth/EnvironmentAuthPolicy") {};
11697
- const make$86 = Effect.gen(function* () {
11850
+ const make$87 = Effect.gen(function* () {
11698
11851
  const config = yield* ServerConfig$1;
11699
11852
  const isRemoteReachable = isRemoteReachableHost(config.host);
11700
11853
  const policy = config.mode === "desktop" ? isRemoteReachable ? "remote-reachable" : "desktop-managed-local" : isRemoteReachable ? "remote-reachable" : "loopback-browser";
@@ -11712,7 +11865,7 @@ const make$86 = Effect.gen(function* () {
11712
11865
  };
11713
11866
  return EnvironmentAuthPolicy.of({ getDescriptor: () => Effect.succeed(descriptor).pipe(Effect.withSpan("EnvironmentAuthPolicy.getDescriptor")) });
11714
11867
  });
11715
- const layer$77 = Layer.effect(EnvironmentAuthPolicy, make$86);
11868
+ const layer$78 = Layer.effect(EnvironmentAuthPolicy, make$87);
11716
11869
  //#endregion
11717
11870
  //#region src/persistence/Errors.ts
11718
11871
  function summarizeSchemaIssue(issue) {
@@ -11893,7 +12046,7 @@ function toPersistenceSqlOrDecodeError$6(sqlOperation, decodeOperation, correlat
11893
12046
  cause
11894
12047
  });
11895
12048
  }
11896
- const make$85 = Effect.gen(function* () {
12049
+ const make$86 = Effect.gen(function* () {
11897
12050
  const sql = yield* SqlClient.SqlClient;
11898
12051
  const createSessionRow = SqlSchema.void({
11899
12052
  Request: CreateAuthSessionInput,
@@ -12027,7 +12180,7 @@ const make$85 = Effect.gen(function* () {
12027
12180
  setLastConnectedAt
12028
12181
  };
12029
12182
  });
12030
- const layer$76 = Layer.effect(AuthSessionRepository, make$85);
12183
+ const layer$77 = Layer.effect(AuthSessionRepository, make$86);
12031
12184
  //#endregion
12032
12185
  //#region src/auth/ServerSecretStore.ts
12033
12186
  const secretStoreErrorContext = {
@@ -12094,7 +12247,7 @@ const isSecretStoreError = Schema$1.is(SecretStoreError);
12094
12247
  const isPlatformError = (value) => Predicate.isTagged(value, "PlatformError");
12095
12248
  const isSecretAlreadyExistsError = (error) => "cause" in error && isPlatformError(error.cause) && error.cause.reason._tag === "AlreadyExists";
12096
12249
  var ServerSecretStore = class extends Context.Service()("@p4code/cli/auth/ServerSecretStore") {};
12097
- const make$84 = Effect.gen(function* () {
12250
+ const make$85 = Effect.gen(function* () {
12098
12251
  const crypto = yield* Crypto.Crypto;
12099
12252
  const fileSystem = yield* FileSystem.FileSystem;
12100
12253
  const path = yield* Path.Path;
@@ -12164,7 +12317,7 @@ const make$84 = Effect.gen(function* () {
12164
12317
  remove
12165
12318
  });
12166
12319
  });
12167
- const layer$75 = Layer.effect(ServerSecretStore, make$84);
12320
+ const layer$76 = Layer.effect(ServerSecretStore, make$85);
12168
12321
  //#endregion
12169
12322
  //#region src/auth/SessionStore.ts
12170
12323
  var MalformedSessionTokenError = class extends Schema$1.TaggedErrorClass()("MalformedSessionTokenError", {}) {
@@ -12402,7 +12555,7 @@ function toAuthClientSession(input) {
12402
12555
  current: false
12403
12556
  };
12404
12557
  }
12405
- const make$83 = Effect.gen(function* () {
12558
+ const make$84 = Effect.gen(function* () {
12406
12559
  const crypto = yield* Crypto.Crypto;
12407
12560
  const serverConfig = yield* ServerConfig$1;
12408
12561
  const secretStore = yield* ServerSecretStore;
@@ -12716,7 +12869,7 @@ const make$83 = Effect.gen(function* () {
12716
12869
  markDisconnected
12717
12870
  });
12718
12871
  });
12719
- const layer$74 = Layer.effect(SessionStore, make$83).pipe(Layer.provideMerge(layer$76));
12872
+ const layer$75 = Layer.effect(SessionStore, make$84).pipe(Layer.provideMerge(layer$77));
12720
12873
  //#endregion
12721
12874
  //#region src/persistence/AuthPairingLinks.ts
12722
12875
  const AuthPairingLinkRecord = Schema$1.Struct({
@@ -12777,7 +12930,7 @@ function toPersistenceSqlOrDecodeError$5(sqlOperation, decodeOperation, correlat
12777
12930
  cause
12778
12931
  });
12779
12932
  }
12780
- const make$82 = Effect.gen(function* () {
12933
+ const make$83 = Effect.gen(function* () {
12781
12934
  const sql = yield* SqlClient.SqlClient;
12782
12935
  const createPairingLinkRow = SqlSchema.void({
12783
12936
  Request: CreateAuthPairingLinkInput,
@@ -12912,7 +13065,7 @@ const make$82 = Effect.gen(function* () {
12912
13065
  getByCredential
12913
13066
  };
12914
13067
  });
12915
- const layer$73 = Layer.effect(AuthPairingLinkRepository, make$82);
13068
+ const layer$74 = Layer.effect(AuthPairingLinkRepository, make$83);
12916
13069
  //#endregion
12917
13070
  //#region src/auth/PairingGrantStore.ts
12918
13071
  var UnknownBootstrapCredentialError = class extends Schema$1.TaggedErrorClass()("UnknownBootstrapCredentialError", {}) {
@@ -13007,7 +13160,7 @@ const DEV_STARTUP_TTL_HOURS = Duration.hours(24);
13007
13160
  const PAIRING_TOKEN_ALPHABET = "23456789ABCDEFGHJKLMNPQRSTUVWXYZ";
13008
13161
  const PAIRING_TOKEN_LENGTH = 12;
13009
13162
  const PAIRING_TOKEN_REJECTION_LIMIT = Math.floor(256 / 32) * 32;
13010
- const make$81 = Effect.gen(function* () {
13163
+ const make$82 = Effect.gen(function* () {
13011
13164
  const crypto = yield* Crypto.Crypto;
13012
13165
  const config = yield* ServerConfig$1;
13013
13166
  const pairingLinks = yield* AuthPairingLinkRepository;
@@ -13205,7 +13358,7 @@ const make$81 = Effect.gen(function* () {
13205
13358
  consume
13206
13359
  });
13207
13360
  });
13208
- const layer$72 = Layer.effect(PairingGrantStore, make$81).pipe(Layer.provideMerge(layer$73));
13361
+ const layer$73 = Layer.effect(PairingGrantStore, make$82).pipe(Layer.provideMerge(layer$74));
13209
13362
  //#endregion
13210
13363
  //#region src/persistence/DatabaseSnapshot.ts
13211
13364
  /**
@@ -15523,7 +15676,7 @@ function parseBearerToken(request) {
15523
15676
  const token = header.slice(7).trim();
15524
15677
  return token.length > 0 ? token : null;
15525
15678
  }
15526
- const make$80 = Effect.gen(function* () {
15679
+ const make$81 = Effect.gen(function* () {
15527
15680
  const policy = yield* EnvironmentAuthPolicy;
15528
15681
  const bootstrapCredentials = yield* PairingGrantStore;
15529
15682
  const sessions = yield* SessionStore;
@@ -15718,9 +15871,9 @@ const make$80 = Effect.gen(function* () {
15718
15871
  issueStartupPairingUrl
15719
15872
  });
15720
15873
  });
15721
- const layer$71 = Layer.effect(EnvironmentAuth, make$80).pipe(Layer.provideMerge(layer$72), Layer.provideMerge(layer$74), Layer.provideMerge(layer$77));
15722
- const storageLayer = Layer.mergeAll(layer$75, layerConfig);
15723
- const runtimeLayer = layer$71.pipe(Layer.provideMerge(storageLayer));
15874
+ const layer$72 = Layer.effect(EnvironmentAuth, make$81).pipe(Layer.provideMerge(layer$73), Layer.provideMerge(layer$75), Layer.provideMerge(layer$78));
15875
+ const storageLayer = Layer.mergeAll(layer$76, layerConfig);
15876
+ const runtimeLayer = layer$72.pipe(Layer.provideMerge(storageLayer));
15724
15877
  //#endregion
15725
15878
  //#region src/cliAuthFormat.ts
15726
15879
  const newline = "\n";
@@ -16475,7 +16628,7 @@ const runWithEnvironmentAuth = (flags, run, options) => Effect.gen(function* ()
16475
16628
  }
16476
16629
  return yield* Effect.gen(function* () {
16477
16630
  return yield* run(yield* EnvironmentAuth);
16478
- }).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$78(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
16631
+ }).pipe(Effect.provide(Layer.mergeAll(runtimeLayer).pipe(Layer.provide(layer$79(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
16479
16632
  });
16480
16633
  const ttlFlag = Flag.string("ttl").pipe(Flag.withSchema(DurationFromString), Flag.withDescription("TTL, for example `5m`, `1h`, `30d`, or `15 minutes`."), Flag.optional);
16481
16634
  const jsonFlag = Flag.boolean("json").pipe(Flag.withDescription("Emit JSON instead of human-readable output."), Flag.withDefault(false));
@@ -16615,7 +16768,7 @@ const DEFAULT_LIMITS = {
16615
16768
  windowMillis: FAILURE_WINDOW_MS,
16616
16769
  blockMillis: BLOCK_DURATION_MS
16617
16770
  };
16618
- const make$79 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
16771
+ const make$80 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LIMITS) {
16619
16772
  const state = yield* Ref.make(initialThrottleState);
16620
16773
  return HubAuthThrottle.of({
16621
16774
  shouldRefuse: Effect.gen(function* () {
@@ -16629,7 +16782,7 @@ const make$79 = Effect.fn("HubAuthThrottle.make")(function* (limits = DEFAULT_LI
16629
16782
  })
16630
16783
  });
16631
16784
  });
16632
- const layer$70 = Layer.effect(HubAuthThrottle, make$79());
16785
+ const layer$71 = Layer.effect(HubAuthThrottle, make$80());
16633
16786
  //#endregion
16634
16787
  //#region src/hub/HubAuth.ts
16635
16788
  /**
@@ -17490,7 +17643,181 @@ const deleteAssetRoute = HttpRouter.add("DELETE", "/assets/:kind/:name", respond
17490
17643
  const outcome = yield* (yield* AgentAssetRepository).deleteByName(requested);
17491
17644
  return outcome._tag === "conflict" ? assetConflict(Option.getOrNull(outcome.current)) : HttpServerResponse.empty({ status: 204 });
17492
17645
  })));
17493
- const layer$69 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, putTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute);
17646
+ const feedSourceColumns = `id, name, kind, feed_url AS "feedUrl", site_url AS "siteUrl",
17647
+ enabled, created_at AS "createdAt", updated_at AS "updatedAt"`;
17648
+ const toFeedSource = (row) => ({
17649
+ ...row,
17650
+ enabled: Boolean(row.enabled)
17651
+ });
17652
+ const FeedArticleWrite = Schema$1.Struct({
17653
+ sourceId: Schema$1.String,
17654
+ canonicalUrl: Schema$1.String,
17655
+ discussionUrl: Schema$1.NullOr(Schema$1.String),
17656
+ title: Schema$1.String,
17657
+ author: Schema$1.NullOr(Schema$1.String),
17658
+ publishedAt: Schema$1.String,
17659
+ fetchedAt: Schema$1.String,
17660
+ contentText: Schema$1.NullOr(Schema$1.String),
17661
+ status: Schema$1.String,
17662
+ contentRevision: Schema$1.String,
17663
+ summary: Schema$1.NullOr(Schema$1.Struct({
17664
+ modelSelection: Schema$1.String,
17665
+ summary: Schema$1.String,
17666
+ highlights: Schema$1.Array(Schema$1.String),
17667
+ references: Schema$1.Array(Schema$1.String),
17668
+ summarizedAt: Schema$1.String
17669
+ })),
17670
+ engagement: Schema$1.Struct({
17671
+ points: Schema$1.NullOr(Schema$1.Number),
17672
+ comments: Schema$1.NullOr(Schema$1.Number),
17673
+ band: Schema$1.String,
17674
+ observedAt: Schema$1.String
17675
+ })
17676
+ });
17677
+ const listFeedSourcesRoute = HttpRouter.add("GET", "/feed/sources", respondToHubFailures(Effect.gen(function* () {
17678
+ yield* authenticateHubRequest();
17679
+ const rows = yield* (yield* SqlClient.SqlClient).unsafe(`SELECT ${feedSourceColumns} FROM feed_sources ORDER BY name`);
17680
+ return HttpServerResponse.jsonUnsafe(rows.map(toFeedSource));
17681
+ })));
17682
+ const upsertFeedSourceRoute = HttpRouter.add("PUT", "/feed/sources", respondToHubFailures(Effect.gen(function* () {
17683
+ yield* authenticateHubRequest();
17684
+ const input = yield* decodeOrInvalid(FeedSourceUpsertInput, "Request body does not match FeedSourceUpsertInput.")(yield* readJsonBody());
17685
+ const sql = yield* SqlClient.SqlClient;
17686
+ const crypto = yield* Crypto.Crypto;
17687
+ const id = input.id ?? FeedSourceId.make(yield* crypto.randomUUIDv4.pipe(Effect.orDie));
17688
+ const now = DateTime.formatIso(yield* DateTime.now);
17689
+ yield* sql`INSERT INTO feed_sources (id, name, kind, feed_url, site_url, enabled, created_at, updated_at)
17690
+ VALUES (${id}, ${input.name}, ${input.kind}, ${input.feedUrl}, ${input.siteUrl}, ${input.enabled ? 1 : 0}, ${now}, ${now})
17691
+ ON CONFLICT(id) DO UPDATE SET name=excluded.name, kind=excluded.kind, feed_url=excluded.feed_url,
17692
+ site_url=excluded.site_url, enabled=excluded.enabled, updated_at=excluded.updated_at`;
17693
+ const rows = yield* sql.unsafe(`SELECT ${feedSourceColumns} FROM feed_sources WHERE id = ?`, [id]);
17694
+ return HttpServerResponse.jsonUnsafe(toFeedSource(rows[0] ?? {}));
17695
+ })));
17696
+ const deleteFeedSourceRoute = HttpRouter.add("DELETE", "/feed/sources/:sourceId", respondToHubFailures(Effect.gen(function* () {
17697
+ yield* authenticateHubRequest();
17698
+ const params = yield* HttpRouter.params;
17699
+ yield* (yield* SqlClient.SqlClient)`DELETE FROM feed_sources WHERE id = ${params.sourceId ?? ""}`;
17700
+ return HttpServerResponse.empty({ status: 204 });
17701
+ })));
17702
+ const listFeedRoute = HttpRouter.add("GET", "/feed/articles", respondToHubFailures(Effect.gen(function* () {
17703
+ yield* authenticateHubRequest();
17704
+ const sql = yield* SqlClient.SqlClient;
17705
+ const articles = yield* sql`
17706
+ SELECT a.id, a.source_id AS "sourceId", s.name AS "sourceName", a.canonical_url AS "canonicalUrl",
17707
+ a.discussion_url AS "discussionUrl", a.title, a.author, a.published_at AS "publishedAt",
17708
+ a.fetched_at AS "fetchedAt", a.content_text AS "contentText", a.status,
17709
+ sm.model_selection AS "modelSelection", sm.summary, sm.highlights_json AS "highlightsJson",
17710
+ sm.references_json AS "referencesJson", sm.summarized_at AS "summarizedAt",
17711
+ e.points, e.comments, COALESCE(e.band, 'unknown') AS band, COALESCE(e.observed_at, a.fetched_at) AS "observedAt",
17712
+ r.read_at AS "readAt"
17713
+ FROM feed_articles a JOIN feed_sources s ON s.id=a.source_id
17714
+ LEFT JOIN feed_summaries sm ON sm.article_id=a.id
17715
+ LEFT JOIN feed_engagement e ON e.article_id=a.id
17716
+ LEFT JOIN feed_read_state r ON r.article_id=a.id ORDER BY a.published_at DESC`;
17717
+ const metadata = yield* sql`SELECT value FROM feed_metadata WHERE key='refreshed_at'`;
17718
+ return HttpServerResponse.jsonUnsafe({
17719
+ articles: articles.map((row) => ({
17720
+ id: row.id,
17721
+ sourceId: row.sourceId,
17722
+ sourceName: row.sourceName,
17723
+ canonicalUrl: row.canonicalUrl,
17724
+ discussionUrl: row.discussionUrl ?? null,
17725
+ title: row.title,
17726
+ author: row.author ?? null,
17727
+ publishedAt: row.publishedAt,
17728
+ fetchedAt: row.fetchedAt,
17729
+ contentText: row.contentText ?? null,
17730
+ status: row.status,
17731
+ readAt: row.readAt ?? null,
17732
+ summary: row.summary == null ? null : {
17733
+ articleId: row.id,
17734
+ modelSelection: row.modelSelection,
17735
+ summary: row.summary,
17736
+ highlights: JSON.parse(String(row.highlightsJson)),
17737
+ references: JSON.parse(String(row.referencesJson)),
17738
+ summarizedAt: row.summarizedAt
17739
+ },
17740
+ engagement: {
17741
+ articleId: row.id,
17742
+ points: row.points ?? null,
17743
+ comments: row.comments ?? null,
17744
+ band: row.band,
17745
+ observedAt: row.observedAt
17746
+ }
17747
+ })),
17748
+ refreshedAt: metadata[0]?.value ?? null
17749
+ });
17750
+ })));
17751
+ const putFeedArticleRoute = HttpRouter.add("PUT", "/feed/articles/:articleId", respondToHubFailures(Effect.gen(function* () {
17752
+ yield* authenticateHubRequest();
17753
+ const params = yield* HttpRouter.params;
17754
+ const body = yield* decodeOrInvalid(FeedArticleWrite, "Request body does not match feed article storage contract.")(yield* readJsonBody());
17755
+ const sql = yield* SqlClient.SqlClient;
17756
+ const id = params.articleId ?? "";
17757
+ yield* sql`INSERT INTO feed_articles (id, source_id, canonical_url, discussion_url, title, author, published_at, fetched_at, content_text, status, content_revision)
17758
+ VALUES (${id}, ${body.sourceId}, ${body.canonicalUrl}, ${body.discussionUrl ?? null}, ${body.title}, ${body.author ?? null}, ${body.publishedAt}, ${body.fetchedAt}, ${body.contentText ?? null}, ${body.status}, ${body.contentRevision})
17759
+ ON CONFLICT(canonical_url) DO UPDATE SET discussion_url=excluded.discussion_url, title=excluded.title,
17760
+ author=excluded.author, published_at=excluded.published_at, fetched_at=excluded.fetched_at,
17761
+ content_text=excluded.content_text, status=excluded.status, content_revision=excluded.content_revision`;
17762
+ if (body.summary) {
17763
+ const summary = body.summary;
17764
+ yield* sql`INSERT INTO feed_summaries (article_id, model_selection, summary, highlights_json, references_json, summarized_at, content_revision)
17765
+ VALUES (${id}, ${summary.modelSelection}, ${summary.summary}, ${JSON.stringify(summary.highlights)}, ${JSON.stringify(summary.references)}, ${summary.summarizedAt}, ${body.contentRevision})
17766
+ ON CONFLICT(article_id) DO UPDATE SET model_selection=excluded.model_selection, summary=excluded.summary,
17767
+ highlights_json=excluded.highlights_json, references_json=excluded.references_json, summarized_at=excluded.summarized_at, content_revision=excluded.content_revision`;
17768
+ }
17769
+ const engagement = body.engagement;
17770
+ yield* sql`INSERT INTO feed_engagement (article_id, points, comments, band, observed_at)
17771
+ VALUES (${id}, ${engagement.points ?? null}, ${engagement.comments ?? null}, ${engagement.band}, ${engagement.observedAt})
17772
+ ON CONFLICT(article_id) DO UPDATE SET points=excluded.points, comments=excluded.comments, band=excluded.band, observed_at=excluded.observed_at`;
17773
+ return HttpServerResponse.empty({ status: 204 });
17774
+ })));
17775
+ const markFeedReadRoute = HttpRouter.add("PUT", "/feed/read", respondToHubFailures(Effect.gen(function* () {
17776
+ yield* authenticateHubRequest();
17777
+ const input = yield* decodeOrInvalid(FeedMarkReadInput, "Request body does not match FeedMarkReadInput.")(yield* readJsonBody());
17778
+ const sql = yield* SqlClient.SqlClient;
17779
+ const readAt = input.read ? DateTime.formatIso(yield* DateTime.now) : null;
17780
+ yield* sql`INSERT INTO feed_read_state (article_id, read_at) VALUES (${input.articleId}, ${readAt})
17781
+ ON CONFLICT(article_id) DO UPDATE SET read_at=excluded.read_at`;
17782
+ return HttpServerResponse.empty({ status: 204 });
17783
+ })));
17784
+ const cleanupFeedRoute = HttpRouter.add("POST", "/feed/cleanup", respondToHubFailures(Effect.gen(function* () {
17785
+ yield* authenticateHubRequest();
17786
+ const input = yield* decodeOrInvalid(FeedCleanupInput, "Request body does not match FeedCleanupInput.")(yield* readJsonBody());
17787
+ const sql = yield* SqlClient.SqlClient;
17788
+ const rows = yield* sql`SELECT COUNT(*) AS count FROM feed_articles WHERE published_at >= ${input.startDate} AND published_at <= ${input.endDate}`;
17789
+ const count = Number(rows[0]?.count ?? 0);
17790
+ if (input.confirm) yield* sql`DELETE FROM feed_articles WHERE published_at >= ${input.startDate} AND published_at <= ${input.endDate}`;
17791
+ return HttpServerResponse.jsonUnsafe({
17792
+ count,
17793
+ deleted: input.confirm
17794
+ });
17795
+ })));
17796
+ const setFeedRefreshedAtRoute = HttpRouter.add("PUT", "/feed/refreshed-at", respondToHubFailures(Effect.gen(function* () {
17797
+ yield* authenticateHubRequest();
17798
+ const body = yield* readJsonBody();
17799
+ if (typeof body.refreshedAt !== "string") return yield* new InvalidHubRequest({ detail: "refreshedAt is required." });
17800
+ yield* (yield* SqlClient.SqlClient)`INSERT INTO feed_metadata (key, value) VALUES ('refreshed_at', ${body.refreshedAt}) ON CONFLICT(key) DO UPDATE SET value=excluded.value`;
17801
+ return HttpServerResponse.empty({ status: 204 });
17802
+ })));
17803
+ const acquireFeedLeaseRoute = HttpRouter.add("POST", "/feed/lease", respondToHubFailures(Effect.gen(function* () {
17804
+ yield* authenticateHubRequest();
17805
+ const body = yield* readJsonBody();
17806
+ if (typeof body.owner !== "string" || typeof body.expiresAt !== "string") return yield* new InvalidHubRequest({ detail: "owner and expiresAt are required." });
17807
+ const sql = yield* SqlClient.SqlClient;
17808
+ yield* sql`DELETE FROM feed_refresh_lease WHERE lease_key='refresh' AND expires_at <= ${DateTime.formatIso(yield* DateTime.now)}`;
17809
+ yield* sql`INSERT INTO feed_refresh_lease (lease_key, owner, expires_at) VALUES ('refresh', ${body.owner}, ${body.expiresAt}) ON CONFLICT(lease_key) DO NOTHING`;
17810
+ const rows = yield* sql`SELECT owner FROM feed_refresh_lease WHERE lease_key='refresh'`;
17811
+ return HttpServerResponse.jsonUnsafe({ acquired: rows[0]?.owner === body.owner });
17812
+ })));
17813
+ const releaseFeedLeaseRoute = HttpRouter.add("DELETE", "/feed/lease", respondToHubFailures(Effect.gen(function* () {
17814
+ yield* authenticateHubRequest();
17815
+ const body = yield* readJsonBody();
17816
+ if (typeof body.owner !== "string") return yield* new InvalidHubRequest({ detail: "owner is required." });
17817
+ yield* (yield* SqlClient.SqlClient)`DELETE FROM feed_refresh_lease WHERE lease_key='refresh' AND owner=${body.owner}`;
17818
+ return HttpServerResponse.empty({ status: 204 });
17819
+ })));
17820
+ const layer$70 = Layer.mergeAll(healthRoute, listTasksRoute, getTaskRoute, createTaskRoute, putTaskRoute, updateTaskRoute, deleteTaskRoute, listAssetsRoute, getAssetRoute, putAssetRoute, deleteAssetRoute, listFeedSourcesRoute, upsertFeedSourceRoute, deleteFeedSourceRoute, listFeedRoute, putFeedArticleRoute, markFeedReadRoute, cleanupFeedRoute, setFeedRefreshedAtRoute, acquireFeedLeaseRoute, releaseFeedLeaseRoute);
17494
17821
  //#endregion
17495
17822
  //#region src/hub/Migrations/001_Tasks.ts
17496
17823
  /**
@@ -17696,6 +18023,77 @@ var _008_TaskExternalRefRemoved_default = Effect.gen(function* () {
17696
18023
  yield* sql`ALTER TABLE tasks DROP COLUMN external_ref_json`;
17697
18024
  });
17698
18025
  //#endregion
18026
+ //#region src/hub/Migrations/009_Feed.ts
18027
+ var _009_Feed_default = Effect.gen(function* () {
18028
+ const sql = yield* SqlClient.SqlClient;
18029
+ yield* sql`CREATE TABLE feed_sources (
18030
+ id TEXT PRIMARY KEY, name TEXT NOT NULL, kind TEXT NOT NULL, feed_url TEXT NOT NULL,
18031
+ site_url TEXT NOT NULL, enabled INTEGER NOT NULL, created_at TEXT NOT NULL, updated_at TEXT NOT NULL
18032
+ )`;
18033
+ yield* sql`CREATE TABLE feed_articles (
18034
+ id TEXT PRIMARY KEY, source_id TEXT NOT NULL REFERENCES feed_sources(id) ON DELETE CASCADE,
18035
+ canonical_url TEXT NOT NULL UNIQUE, discussion_url TEXT, title TEXT NOT NULL, author TEXT,
18036
+ published_at TEXT NOT NULL, fetched_at TEXT NOT NULL, content_text TEXT, status TEXT NOT NULL,
18037
+ content_revision TEXT NOT NULL
18038
+ )`;
18039
+ yield* sql`CREATE TABLE feed_summaries (
18040
+ article_id TEXT PRIMARY KEY REFERENCES feed_articles(id) ON DELETE CASCADE,
18041
+ model_selection TEXT NOT NULL, summary TEXT NOT NULL, highlights_json TEXT NOT NULL,
18042
+ references_json TEXT NOT NULL, summarized_at TEXT NOT NULL, content_revision TEXT NOT NULL
18043
+ )`;
18044
+ yield* sql`CREATE TABLE feed_engagement (
18045
+ article_id TEXT PRIMARY KEY REFERENCES feed_articles(id) ON DELETE CASCADE,
18046
+ points INTEGER, comments INTEGER, band TEXT NOT NULL, observed_at TEXT NOT NULL
18047
+ )`;
18048
+ yield* sql`CREATE TABLE feed_read_state (
18049
+ article_id TEXT PRIMARY KEY REFERENCES feed_articles(id) ON DELETE CASCADE, read_at TEXT
18050
+ )`;
18051
+ yield* sql`CREATE TABLE feed_refresh_lease (
18052
+ lease_key TEXT PRIMARY KEY, owner TEXT NOT NULL, expires_at TEXT NOT NULL
18053
+ )`;
18054
+ yield* sql`CREATE TABLE feed_metadata (key TEXT PRIMARY KEY, value TEXT NOT NULL)`;
18055
+ yield* sql`CREATE INDEX idx_feed_articles_published ON feed_articles(published_at DESC)`;
18056
+ const now = DateTime.formatIso(yield* DateTime.now);
18057
+ for (const [id, name, kind, feedUrl, siteUrl] of [
18058
+ [
18059
+ "hacker-news",
18060
+ "Hacker News",
18061
+ "hacker_news",
18062
+ "https://hnrss.org/frontpage",
18063
+ "https://news.ycombinator.com"
18064
+ ],
18065
+ [
18066
+ "techcrunch",
18067
+ "TechCrunch",
18068
+ "syndication",
18069
+ "https://techcrunch.com/feed/",
18070
+ "https://techcrunch.com"
18071
+ ],
18072
+ [
18073
+ "the-verge",
18074
+ "The Verge",
18075
+ "syndication",
18076
+ "https://www.theverge.com/rss/index.xml",
18077
+ "https://www.theverge.com"
18078
+ ],
18079
+ [
18080
+ "ars-technica",
18081
+ "Ars Technica",
18082
+ "syndication",
18083
+ "https://feeds.arstechnica.com/arstechnica/index",
18084
+ "https://arstechnica.com"
18085
+ ],
18086
+ [
18087
+ "wired",
18088
+ "Wired",
18089
+ "syndication",
18090
+ "https://www.wired.com/feed/rss",
18091
+ "https://www.wired.com"
18092
+ ]
18093
+ ]) yield* sql`INSERT INTO feed_sources (id, name, kind, feed_url, site_url, enabled, created_at, updated_at)
18094
+ VALUES (${id}, ${name}, ${kind}, ${feedUrl}, ${siteUrl}, 1, ${now}, ${now})`;
18095
+ });
18096
+ //#endregion
17699
18097
  //#region src/hub/Migrations.ts
17700
18098
  /**
17701
18099
  * Hub migrations.
@@ -17746,6 +18144,11 @@ const hubMigrationEntries = [
17746
18144
  8,
17747
18145
  "TaskExternalRefRemoved",
17748
18146
  _008_TaskExternalRefRemoved_default
18147
+ ],
18148
+ [
18149
+ 9,
18150
+ "Feed",
18151
+ _009_Feed_default
17749
18152
  ]
17750
18153
  ];
17751
18154
  const hubMigrationLoader = Migrator.fromRecord(Object.fromEntries(hubMigrationEntries.map(([id, name, migration]) => [`${id}_${name}`, migration])));
@@ -17828,7 +18231,7 @@ const announce = Layer.effectDiscard(Effect.gen(function* () {
17828
18231
  });
17829
18232
  if (isRemoteReachableHost(config.host)) yield* Effect.logWarning("Hub is reachable beyond loopback. The bearer token is the only control — repeated auth failures are not rate limited.", { host: config.host });
17830
18233
  }));
17831
- const makeHubLayer = HttpRouter.serve(layer$69).pipe(Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$70), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
18234
+ const makeHubLayer = HttpRouter.serve(layer$70).pipe(Layer.provideMerge(announce), Layer.provideMerge(HubHttpServerLive), Layer.provideMerge(layer$71), Layer.provideMerge(TaskRepositoryLive), Layer.provideMerge(AgentAssetRepositoryLive), Layer.provideMerge(HubPersistenceLive));
17832
18235
  const runHub = Layer.launch(makeHubLayer);
17833
18236
  //#endregion
17834
18237
  //#region src/atomicWrite.ts
@@ -17952,7 +18355,7 @@ function stripDefaultServerSettings(current, defaults) {
17952
18355
  }
17953
18356
  return Object.is(current, defaults) ? void 0 : current;
17954
18357
  }
17955
- const make$78 = Effect.gen(function* () {
18358
+ const make$79 = Effect.gen(function* () {
17956
18359
  const { settingsPath } = yield* ServerConfig$1;
17957
18360
  const fs = yield* FileSystem.FileSystem;
17958
18361
  const pathService = yield* Path.Path;
@@ -18173,7 +18576,7 @@ const make$78 = Effect.gen(function* () {
18173
18576
  }
18174
18577
  };
18175
18578
  });
18176
- const layer$68 = Layer.effect(ServerSettingsService, make$78);
18579
+ const layer$69 = Layer.effect(ServerSettingsService, make$79);
18177
18580
  //#endregion
18178
18581
  //#region src/pathExpansion.ts
18179
18582
  /**
@@ -18547,7 +18950,7 @@ function claudeEntryFromRegistration(registration) {
18547
18950
  };
18548
18951
  }
18549
18952
  var ClaudeMcpFiles = class extends Context.Service()("@p4code/cli/mcp/ClaudeMcpFiles") {};
18550
- const make$77 = Effect.gen(function* () {
18953
+ const make$78 = Effect.gen(function* () {
18551
18954
  const fileSystem = yield* FileSystem.FileSystem;
18552
18955
  const path = yield* Path.Path;
18553
18956
  const services = yield* Effect.context();
@@ -18612,7 +19015,7 @@ const make$77 = Effect.gen(function* () {
18612
19015
  removeProject: (projectDir, name) => removeAt(Effect.succeed(projectFile(projectDir)))(name)
18613
19016
  };
18614
19017
  });
18615
- const layer$67 = Layer.effect(ClaudeMcpFiles, make$77);
19018
+ const layer$68 = Layer.effect(ClaudeMcpFiles, make$78);
18616
19019
  Layer.succeed(ClaudeMcpFiles, {
18617
19020
  readUser: Effect.succeed([]),
18618
19021
  upsertUser: () => Effect.fail(new McpRegistryError({ detail: "No Claude config in tests." })),
@@ -18748,7 +19151,7 @@ const decodeClientRegistration = Schema$1.decodeUnknownExit(ClientRegistrationRe
18748
19151
  const decodeTokenResponse = Schema$1.decodeUnknownExit(TokenResponse);
18749
19152
  var McpOAuth = class extends Context.Service()("@p4code/cli/mcp/McpOAuth") {};
18750
19153
  const registryError = (detail) => new McpRegistryError({ detail });
18751
- const make$76 = Effect.gen(function* () {
19154
+ const make$77 = Effect.gen(function* () {
18752
19155
  const config = yield* ServerConfig$1;
18753
19156
  const secrets = yield* ServerSecretStore;
18754
19157
  const http = yield* HttpClient.HttpClient;
@@ -19068,7 +19471,7 @@ const make$76 = Effect.gen(function* () {
19068
19471
  accessTokenFor
19069
19472
  };
19070
19473
  });
19071
- const layer$66 = Layer.effect(McpOAuth, make$76);
19474
+ const layer$67 = Layer.effect(McpOAuth, make$77);
19072
19475
  Layer.succeed(McpOAuth, {
19073
19476
  statusFor: () => Effect.succeed(Option.none()),
19074
19477
  begin: () => Effect.fail(new McpRegistryError({ detail: "OAuth sign-in is not available." })),
@@ -19086,7 +19489,7 @@ const decodeRegistration$1 = Schema$1.decodeUnknownExit(RegistrationFromJson$1);
19086
19489
  const encodeRegistration = Schema$1.encodeSync(RegistrationFromJson$1);
19087
19490
  var McpRegistry = class extends Context.Service()("@p4code/cli/mcp/McpRegistry") {};
19088
19491
  const slotsOf = (registration) => registration.secrets ?? [];
19089
- const make$75 = Effect.gen(function* () {
19492
+ const make$76 = Effect.gen(function* () {
19090
19493
  const config = yield* ServerConfig$1;
19091
19494
  const secrets = yield* ServerSecretStore;
19092
19495
  const oauth = yield* McpOAuth;
@@ -19237,7 +19640,7 @@ const make$75 = Effect.gen(function* () {
19237
19640
  }).pipe(Effect.provide(services), Effect.catchCause((cause) => Effect.logWarning("mcp registry resolve failed", { cause }).pipe(Effect.as({}))))
19238
19641
  };
19239
19642
  });
19240
- const layer$65 = Layer.effect(McpRegistry, make$75);
19643
+ const layer$66 = Layer.effect(McpRegistry, make$76);
19241
19644
  //#endregion
19242
19645
  //#region src/sync/skillDirectory.ts
19243
19646
  /**
@@ -19616,7 +20019,7 @@ const formatHubLink = (input) => encodeStoredHubLink({
19616
20019
  shareMode: input.shareMode
19617
20020
  });
19618
20021
  const fromEnvironment = (environment) => validateHubLink(environment.P4CODE_HUB_URL ?? "", environment.P4CODE_HUB_TOKEN ?? "");
19619
- const make$74 = Effect.fn("HubLink.make")(function* (environment) {
20022
+ const make$75 = Effect.fn("HubLink.make")(function* (environment) {
19620
20023
  const secrets = yield* ServerSecretStore;
19621
20024
  const env = environment ?? process.env;
19622
20025
  const fromEnv = fromEnvironment(env);
@@ -19682,7 +20085,7 @@ const make$74 = Effect.fn("HubLink.make")(function* (environment) {
19682
20085
  })
19683
20086
  };
19684
20087
  });
19685
- const layer$64 = Layer.effect(HubLink, make$74());
20088
+ const layer$65 = Layer.effect(HubLink, make$75());
19686
20089
  //#endregion
19687
20090
  //#region src/sync/HubAssetClient.ts
19688
20091
  /**
@@ -19715,7 +20118,7 @@ const decodeAssetListPage = Schema$1.decodeUnknownEffect(AssetListPage);
19715
20118
  const decodeConflictBody$1 = Schema$1.decodeUnknownEffect(ConflictBody$1);
19716
20119
  const decodeAsset = Schema$1.decodeUnknownEffect(AgentAsset);
19717
20120
  var HubAssetClient = class extends Context.Service()("@p4code/cli/sync/HubAssetClient") {};
19718
- const make$73 = Effect.gen(function* () {
20121
+ const make$74 = Effect.gen(function* () {
19719
20122
  const http = yield* HttpClient.HttpClient;
19720
20123
  const link = yield* HubLink;
19721
20124
  const requireSettings = Effect.gen(function* () {
@@ -19797,7 +20200,7 @@ const make$73 = Effect.gen(function* () {
19797
20200
  remove
19798
20201
  };
19799
20202
  });
19800
- const layer$63 = Layer.effect(HubAssetClient, make$73);
20203
+ const layer$64 = Layer.effect(HubAssetClient, make$74);
19801
20204
  //#endregion
19802
20205
  //#region src/sync/mcpRegistrationFiles.ts
19803
20206
  /**
@@ -20372,7 +20775,7 @@ const EMPTY_REPORT = {
20372
20775
  unavailable: null
20373
20776
  };
20374
20777
  var AssetSync = class extends Context.Service()("@p4code/cli/sync/AssetSync") {};
20375
- const make$72 = Effect.gen(function* () {
20778
+ const make$73 = Effect.gen(function* () {
20376
20779
  const client = yield* HubAssetClient;
20377
20780
  const link = yield* HubLink;
20378
20781
  const settingsStore = yield* ServerSettingsService;
@@ -21085,7 +21488,7 @@ const make$72 = Effect.gen(function* () {
21085
21488
  removeLocal
21086
21489
  };
21087
21490
  });
21088
- const layer$62 = Layer.effect(AssetSync, make$72);
21491
+ const layer$63 = Layer.effect(AssetSync, make$73);
21089
21492
  //#endregion
21090
21493
  //#region src/provider/CompressPrompts.ts
21091
21494
  /**
@@ -21436,7 +21839,7 @@ const findAgentPreset = (requested) => {
21436
21839
  };
21437
21840
  //#endregion
21438
21841
  //#region src/cli/assets.ts
21439
- const SyncServicesLive = layer$62.pipe(Layer.provideMerge(layer$63), Layer.provideMerge(layer$64), Layer.provideMerge(layer$68.pipe(Layer.provide(layer$75))), Layer.provideMerge(layer$75), Layer.provideMerge(FetchHttpClient.layer));
21842
+ const SyncServicesLive = layer$63.pipe(Layer.provideMerge(layer$64), Layer.provideMerge(layer$65), Layer.provideMerge(layer$69.pipe(Layer.provide(layer$76))), Layer.provideMerge(layer$76), Layer.provideMerge(FetchHttpClient.layer));
21440
21843
  const runWithSync = (flags, run) => Effect.gen(function* () {
21441
21844
  const config = yield* resolveCliAuthConfig(flags, yield* GlobalFlag.LogLevel);
21442
21845
  return yield* Effect.gen(function* () {
@@ -21444,7 +21847,7 @@ const runWithSync = (flags, run) => Effect.gen(function* () {
21444
21847
  sync: yield* AssetSync,
21445
21848
  link: yield* HubLink
21446
21849
  });
21447
- }).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$78(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
21850
+ }).pipe(Effect.provide(SyncServicesLive.pipe(Layer.provide(layer$79(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, "Error")))));
21448
21851
  });
21449
21852
  const STATE_LABEL = {
21450
21853
  synced: "synced",
@@ -27154,12 +27557,12 @@ const runProcessCore = Effect.fn("processRunner.runProcessCore")(function* (spaw
27154
27557
  stderrInvalidUtf8: stderr.invalidUtf8
27155
27558
  };
27156
27559
  });
27157
- const make$71 = Effect.fn("ProcessRunner.make")(function* () {
27560
+ const make$72 = Effect.fn("ProcessRunner.make")(function* () {
27158
27561
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
27159
27562
  const run = (input) => finalizeRunProcess(runProcessCore(spawner, input), input);
27160
27563
  return ProcessRunner.of({ run });
27161
27564
  });
27162
- const layer$61 = Layer.effect(ProcessRunner, make$71());
27565
+ const layer$62 = Layer.effect(ProcessRunner, make$72());
27163
27566
  //#endregion
27164
27567
  //#region src/project/RepositoryIdentityResolver.ts
27165
27568
  const DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY = 512;
@@ -27250,7 +27653,7 @@ const resolveRepositoryIdentityFromCacheKey = Effect.fn("RepositoryIdentityResol
27250
27653
  rootPath: cacheKey
27251
27654
  }) : null;
27252
27655
  });
27253
- const make$70 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
27656
+ const make$71 = Effect.fn("RepositoryIdentityResolver.make")(function* (options = {}) {
27254
27657
  const processRunner = yield* ProcessRunner;
27255
27658
  const repositoryIdentityCache = yield* Cache.makeWith((cacheKey) => resolveRepositoryIdentityFromCacheKey(cacheKey).pipe(Effect.provideService(ProcessRunner, processRunner)), {
27256
27659
  capacity: options.cacheCapacity ?? DEFAULT_REPOSITORY_IDENTITY_CACHE_CAPACITY,
@@ -27265,7 +27668,7 @@ const make$70 = Effect.fn("RepositoryIdentityResolver.make")(function* (options
27265
27668
  });
27266
27669
  return RepositoryIdentityResolver.of({ resolve });
27267
27670
  });
27268
- const layer$60 = Layer.effect(RepositoryIdentityResolver, make$70()).pipe(Layer.provide(layer$61));
27671
+ const layer$61 = Layer.effect(RepositoryIdentityResolver, make$71()).pipe(Layer.provide(layer$62));
27269
27672
  //#endregion
27270
27673
  //#region src/orchestration/Layers/ProjectionSnapshotQuery.ts
27271
27674
  const decodeReadModel = Schema$1.decodeUnknownEffect(OrchestrationReadModel);
@@ -29307,7 +29710,7 @@ function mergeWithDefaultKeybindings(custom) {
29307
29710
  * Keybindings - Service tag for keybinding configuration operations.
29308
29711
  */
29309
29712
  var Keybindings = class extends Context.Service()("@p4code/cli/keybindings") {};
29310
- const make$69 = Effect.gen(function* () {
29713
+ const make$70 = Effect.gen(function* () {
29311
29714
  const { keybindingsConfigPath } = yield* ServerConfig$1;
29312
29715
  const fs = yield* FileSystem.FileSystem;
29313
29716
  const path = yield* Path.Path;
@@ -29568,7 +29971,7 @@ const make$69 = Effect.gen(function* () {
29568
29971
  }))
29569
29972
  };
29570
29973
  });
29571
- const layer$59 = Layer.effect(Keybindings, make$69);
29974
+ const layer$60 = Layer.effect(Keybindings, make$70);
29572
29975
  //#endregion
29573
29976
  //#region src/process/externalLauncher.ts
29574
29977
  /**
@@ -29795,7 +30198,7 @@ const launchEditorProcess = Effect.fn("externalLauncher.launchEditorProcess")(fu
29795
30198
  cause
29796
30199
  }));
29797
30200
  });
29798
- const make$68 = Effect.gen(function* () {
30201
+ const make$69 = Effect.gen(function* () {
29799
30202
  const spawner = yield* ChildProcessSpawner$1.ChildProcessSpawner;
29800
30203
  const fileSystem = yield* FileSystem.FileSystem;
29801
30204
  const path = yield* Path.Path;
@@ -29806,7 +30209,7 @@ const make$68 = Effect.gen(function* () {
29806
30209
  launchEditor: (input) => provideCommandResolutionServices(Effect.flatMap(resolveEditorLaunch(input), (launch) => launchEditorProcess(launch).pipe(Effect.provideService(ChildProcessSpawner$1.ChildProcessSpawner, spawner))))
29807
30210
  });
29808
30211
  });
29809
- const layer$58 = Layer.effect(ExternalLauncher, make$68);
30212
+ const layer$59 = Layer.effect(ExternalLauncher, make$69);
29810
30213
  //#endregion
29811
30214
  //#region src/orchestration/Services/OrchestrationReactor.ts
29812
30215
  /**
@@ -29824,7 +30227,7 @@ var OrchestrationReactor = class extends Context.Service()("@p4code/cli/orchestr
29824
30227
  //#endregion
29825
30228
  //#region src/serverLifecycleEvents.ts
29826
30229
  var ServerLifecycleEvents = class extends Context.Service()("@p4code/cli/serverLifecycleEvents") {};
29827
- const make$67 = Effect.gen(function* () {
30230
+ const make$68 = Effect.gen(function* () {
29828
30231
  const pubsub = yield* PubSub.unbounded();
29829
30232
  const state = yield* Ref.make({
29830
30233
  sequence: 0,
@@ -29848,7 +30251,7 @@ const make$67 = Effect.gen(function* () {
29848
30251
  }
29849
30252
  };
29850
30253
  });
29851
- const layer$57 = Layer.effect(ServerLifecycleEvents, make$67);
30254
+ const layer$58 = Layer.effect(ServerLifecycleEvents, make$68);
29852
30255
  //#endregion
29853
30256
  //#region src/telemetry/Identify.ts
29854
30257
  const CodexAuthJsonSchema = Schema$1.Struct({ tokens: Schema$1.Struct({ account_id: Schema$1.String }) });
@@ -30021,7 +30424,7 @@ var AnalyticsService = class AnalyticsService extends Context.Service()("@p4code
30021
30424
  /** No-op layer for callers that intentionally disable telemetry. */
30022
30425
  static layerTest = Layer.succeed(AnalyticsService, inert);
30023
30426
  };
30024
- const make$66 = Effect.gen(function* () {
30427
+ const make$67 = Effect.gen(function* () {
30025
30428
  const telemetryConfig = yield* TelemetryEnvConfig;
30026
30429
  const posthogKey = telemetryConfig.posthogKey.trim();
30027
30430
  if (!telemetryConfig.enabled || posthogKey === "") return inert;
@@ -30091,7 +30494,7 @@ const make$66 = Effect.gen(function* () {
30091
30494
  flush
30092
30495
  });
30093
30496
  });
30094
- const layer$56 = Layer.effect(AnalyticsService, make$66);
30497
+ const layer$57 = Layer.effect(AnalyticsService, make$67);
30095
30498
  AnalyticsService.layerTest;
30096
30499
  //#endregion
30097
30500
  //#region src/service/pinnedRuntime.ts
@@ -30438,7 +30841,7 @@ var BootServiceInstallError = class extends Schema$1.TaggedErrorClass()("BootSer
30438
30841
  }
30439
30842
  };
30440
30843
  var BootService = class extends Context.Service()("@p4code/cli/service/bootService") {};
30441
- const make$65 = Effect.fn("cloud.boot_service.make")(function* (input) {
30844
+ const make$66 = Effect.fn("cloud.boot_service.make")(function* (input) {
30442
30845
  const hostExecPath = yield* HostProcessExecutablePath;
30443
30846
  const hostArguments = yield* HostProcessArguments;
30444
30847
  const host = input.host ?? {
@@ -30660,7 +31063,7 @@ const make$65 = Effect.fn("cloud.boot_service.make")(function* (input) {
30660
31063
  logPath
30661
31064
  });
30662
31065
  });
30663
- const layer$55 = (input) => Layer.effect(BootService, make$65(input));
31066
+ const layer$56 = (input) => Layer.effect(BootService, make$66(input));
30664
31067
  //#endregion
30665
31068
  //#region src/service/selfUpdate.ts
30666
31069
  /**
@@ -30735,7 +31138,7 @@ const resolveServerSelfUpdateCapability = Effect.fn("cloud.server_self_update.re
30735
31138
  return null;
30736
31139
  });
30737
31140
  var ServerSelfUpdate = class extends Context.Service()("@p4code/cli/service/selfUpdate/ServerSelfUpdate") {};
30738
- const make$64 = Effect.fn("cloud.server_self_update.make")(function* (options) {
31141
+ const make$65 = Effect.fn("cloud.server_self_update.make")(function* (options) {
30739
31142
  const serverConfig = yield* ServerConfig$1;
30740
31143
  const fs = yield* FileSystem.FileSystem;
30741
31144
  const path = yield* Path.Path;
@@ -30885,7 +31288,7 @@ const make$64 = Effect.fn("cloud.server_self_update.make")(function* (options) {
30885
31288
  });
30886
31289
  return ServerSelfUpdate.of({ update });
30887
31290
  });
30888
- const layer$54 = Layer.effect(ServerSelfUpdate, make$64()).pipe(Layer.provide(layer$61));
31291
+ const layer$55 = Layer.effect(ServerSelfUpdate, make$65()).pipe(Layer.provide(layer$62));
30889
31292
  //#endregion
30890
31293
  //#region src/environment/ServerEnvironmentLabel.ts
30891
31294
  const ServerEnvironmentLabelCommandProbe = Schema$1.Literals(["macos-computer-name", "linux-pretty-hostname"]);
@@ -31017,7 +31420,7 @@ function platformArch(architecture) {
31017
31420
  default: return "other";
31018
31421
  }
31019
31422
  }
31020
- const make$63 = Effect.gen(function* () {
31423
+ const make$64 = Effect.gen(function* () {
31021
31424
  const fileSystem = yield* FileSystem.FileSystem;
31022
31425
  const path = yield* Path.Path;
31023
31426
  const serverConfig = yield* ServerConfig$1;
@@ -31081,7 +31484,7 @@ const make$63 = Effect.gen(function* () {
31081
31484
  * state. It intentionally has no fallback Layer.succeed value: callers must
31082
31485
  * provide the external platform services and a ServerConfig.
31083
31486
  */
31084
- const layer$53 = Layer.effect(ServerEnvironment, make$63).pipe(Layer.provide(layer$61));
31487
+ const layer$54 = Layer.effect(ServerEnvironment, make$64).pipe(Layer.provide(layer$62));
31085
31488
  //#endregion
31086
31489
  //#region src/provider/Services/ProviderSessionReaper.ts
31087
31490
  var ProviderSessionReaper = class extends Context.Service()("@p4code/cli/provider/Services/ProviderSessionReaper") {};
@@ -32159,7 +32562,7 @@ const maybeOpenBrowser = (target) => Effect.gen(function* () {
32159
32562
  yield* (yield* ExternalLauncher).launchBrowser(target).pipe(Effect.catch(() => Effect.logInfo("browser auto-open unavailable", { hint: `Open ${target} in your browser.` })));
32160
32563
  });
32161
32564
  const runStartupPhase = (phase, effect) => effect.pipe(Effect.annotateSpans({ "startup.phase": phase }), Effect.withSpan(`server.startup.${phase}`));
32162
- const make$62 = Effect.gen(function* () {
32565
+ const make$63 = Effect.gen(function* () {
32163
32566
  const serverConfig = yield* ServerConfig$1;
32164
32567
  const keybindings = yield* Keybindings;
32165
32568
  const orchestrationReactor = yield* OrchestrationReactor;
@@ -32300,7 +32703,7 @@ const make$62 = Effect.gen(function* () {
32300
32703
  enqueueCommand: commandGate.enqueueCommand
32301
32704
  };
32302
32705
  });
32303
- const layer$52 = Layer.effect(ServerRuntimeStartup, make$62);
32706
+ const layer$53 = Layer.effect(ServerRuntimeStartup, make$63);
32304
32707
  //#endregion
32305
32708
  //#region src/serverRuntimeState.ts
32306
32709
  const PersistedServerRuntimeState = Schema$1.Struct({
@@ -32457,7 +32860,7 @@ function expandHomePath$2(input, path) {
32457
32860
  if (input.startsWith("~/") || input.startsWith("~\\")) return path.join(NodeOS.homedir(), input.slice(2));
32458
32861
  return input;
32459
32862
  }
32460
- const make$61 = Effect.gen(function* () {
32863
+ const make$62 = Effect.gen(function* () {
32461
32864
  const fileSystem = yield* FileSystem.FileSystem;
32462
32865
  const path = yield* Path.Path;
32463
32866
  const statWorkspaceRoot = Effect.fn("WorkspacePaths.statWorkspaceRoot")(function* (workspaceRoot, normalizedWorkspaceRoot, phase) {
@@ -32514,7 +32917,7 @@ const make$61 = Effect.gen(function* () {
32514
32917
  resolveRelativePathWithinRoot
32515
32918
  });
32516
32919
  });
32517
- const layer$51 = Layer.effect(WorkspacePaths, make$61);
32920
+ const layer$52 = Layer.effect(WorkspacePaths, make$62);
32518
32921
  //#endregion
32519
32922
  //#region src/cli/project.ts
32520
32923
  const isEnvironmentHttpCommonError = Schema$1.is(EnvironmentHttpCommonError);
@@ -32620,7 +33023,7 @@ const projectCommandUuid = Crypto.Crypto.pipe(Effect.flatMap((crypto) => crypto.
32620
33023
  operation: "generateProjectCommandId",
32621
33024
  cause
32622
33025
  })));
32623
- const ProjectCliRuntimeLive = Layer.mergeAll(layer$51, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$60), Layer.provideMerge(layerConfig)));
33026
+ const ProjectCliRuntimeLive = Layer.mergeAll(layer$52, OrchestrationLayerLive.pipe(Layer.provideMerge(layer$61), Layer.provideMerge(layerConfig)));
32624
33027
  const PROJECT_CLI_LIVE_SERVER_TIMEOUT = Duration.seconds(1);
32625
33028
  const withProjectCliSessionToken = (environmentAuth, run) => Effect.acquireUseRelease(environmentAuth.issueSession({
32626
33029
  scopes: AuthAdministrativeScopes,
@@ -32711,7 +33114,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
32711
33114
  });
32712
33115
  yield* Console.log(output);
32713
33116
  }));
32714
- const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$78(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
33117
+ const offlineRuntimeLayer = ProjectCliRuntimeLive.pipe(Layer.provide(layer$79(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)));
32715
33118
  return yield* Effect.gen(function* () {
32716
33119
  const snapshot = yield* getOfflineSnapshot();
32717
33120
  const orchestrationEngine = yield* OrchestrationEngineService;
@@ -32722,7 +33125,7 @@ const runProjectMutation = Effect.fn("runProjectMutation")(function* (flags, run
32722
33125
  });
32723
33126
  yield* Console.log(output);
32724
33127
  }).pipe(Effect.provide(offlineRuntimeLayer));
32725
- }).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$51).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$78(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
33128
+ }).pipe(Effect.provide(Layer.mergeAll(runtimeLayer, layer$52).pipe(Layer.provideMerge(FetchHttpClient.layer), Layer.provide(layer$79(config)), Layer.provide(Layer.succeed(References.MinimumLogLevel, minimumLogLevel)))));
32726
33129
  });
32727
33130
  const projectAddCommand = Command.make("add", {
32728
33131
  ...projectLocationFlags,
@@ -33697,7 +34100,7 @@ const logP4ProjectFileLoadError = (error) => Effect.logWarning(error).pipe(Effec
33697
34100
  filePath: error.filePath,
33698
34101
  errorTag: error._tag
33699
34102
  }));
33700
- const make$60 = Effect.gen(function* () {
34103
+ const make$61 = Effect.gen(function* () {
33701
34104
  const fileSystem = yield* FileSystem.FileSystem;
33702
34105
  const path = yield* Path.Path;
33703
34106
  const load = Effect.fn("P4ProjectFileLoader.load")(function* (workspaceRoot) {
@@ -33718,7 +34121,7 @@ const make$60 = Effect.gen(function* () {
33718
34121
  });
33719
34122
  return P4ProjectFileLoader.of({ load });
33720
34123
  });
33721
- const layer$50 = Layer.effect(P4ProjectFileLoader, make$60);
34124
+ const layer$51 = Layer.effect(P4ProjectFileLoader, make$61);
33722
34125
  //#endregion
33723
34126
  //#region src/project/ProjectFaviconResolver.ts
33724
34127
  /**
@@ -33793,7 +34196,7 @@ function extractIconHref(source) {
33793
34196
  return null;
33794
34197
  }
33795
34198
  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) }));
33796
- const make$59 = Effect.gen(function* () {
34199
+ const make$60 = Effect.gen(function* () {
33797
34200
  const fileSystem = yield* FileSystem.FileSystem;
33798
34201
  const path = yield* Path.Path;
33799
34202
  const workspacePaths = yield* WorkspacePaths;
@@ -33862,7 +34265,7 @@ const make$59 = Effect.gen(function* () {
33862
34265
  });
33863
34266
  return ProjectFaviconResolver.of({ resolvePath });
33864
34267
  });
33865
- const layer$49 = Layer.effect(ProjectFaviconResolver, make$59);
34268
+ const layer$50 = Layer.effect(ProjectFaviconResolver, make$60);
33866
34269
  //#endregion
33867
34270
  //#region src/assets/AssetAccess.ts
33868
34271
  const ASSET_ROUTE_PREFIX = "/api/assets";
@@ -34273,10 +34676,10 @@ const resolveAsset = Effect.fn("AssetAccess.resolveAsset")(function* (token, rel
34273
34676
  //#endregion
34274
34677
  //#region src/observability/BrowserTraceCollector.ts
34275
34678
  var BrowserTraceCollector = class extends Context.Service()("@p4code/cli/observability/BrowserTraceCollector") {};
34276
- const make$58 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
34679
+ const make$59 = (sink) => BrowserTraceCollector.of({ record: (records) => Effect.sync(() => {
34277
34680
  for (const record of records) sink.push(record);
34278
34681
  }) });
34279
- const layer$48 = (sink) => Layer.succeed(BrowserTraceCollector, make$58(sink));
34682
+ const layer$49 = (sink) => Layer.succeed(BrowserTraceCollector, make$59(sink));
34280
34683
  //#endregion
34281
34684
  //#region src/auth/http.ts
34282
34685
  const CREDENTIAL_RESPONSE_HEADERS = {
@@ -37329,7 +37732,7 @@ const classifyNonZeroExit = (command, stderr) => {
37329
37732
  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";
37330
37733
  return "command-failed";
37331
37734
  };
37332
- const make$57 = Effect.gen(function* () {
37735
+ const make$58 = Effect.gen(function* () {
37333
37736
  const processRunner = yield* ProcessRunner;
37334
37737
  const run = Effect.fn("VcsProcess.run")(function* (input) {
37335
37738
  const baseError = {
@@ -37388,7 +37791,7 @@ const make$57 = Effect.gen(function* () {
37388
37791
  });
37389
37792
  return VcsProcess.of({ run });
37390
37793
  });
37391
- const layer$47 = Layer.effect(VcsProcess, make$57).pipe(Layer.provide(layer$61));
37794
+ const layer$48 = Layer.effect(VcsProcess, make$58).pipe(Layer.provide(layer$62));
37392
37795
  //#endregion
37393
37796
  //#region src/vcs/VcsDriver.ts
37394
37797
  var VcsDriver = class extends Context.Service()("@p4code/cli/vcs/VcsDriver") {};
@@ -37839,12 +38242,12 @@ const makeVcsDriver = Effect.gen(function* () {
37839
38242
  const driver = yield* makeVcsDriverShape();
37840
38243
  return VcsDriver.of(driver);
37841
38244
  });
37842
- const make$56 = Effect.gen(function* () {
38245
+ const make$57 = Effect.gen(function* () {
37843
38246
  const git = yield* makeGitVcsDriverCore();
37844
38247
  return GitVcsDriver.of(git);
37845
38248
  });
37846
38249
  Layer.effect(VcsDriver, makeVcsDriver);
37847
- const layer$46 = Layer.effect(GitVcsDriver, make$56);
38250
+ const layer$47 = Layer.effect(GitVcsDriver, make$57);
37848
38251
  //#endregion
37849
38252
  //#region src/vcs/VcsProjectConfig.ts
37850
38253
  const ProjectVcsConfigJson = fromLenientJson(Schema$1.Struct({
@@ -37876,7 +38279,7 @@ const logVcsProjectConfigError = (error) => Effect.logWarning(error).pipe(Effect
37876
38279
  configPath: error.configPath,
37877
38280
  errorTag: error._tag
37878
38281
  }));
37879
- const make$55 = Effect.gen(function* () {
38282
+ const make$56 = Effect.gen(function* () {
37880
38283
  const fileSystem = yield* FileSystem.FileSystem;
37881
38284
  const path = yield* Path.Path;
37882
38285
  const findConfigPath = Effect.fn("VcsProjectConfig.findConfigPath")(function* (cwd) {
@@ -37917,7 +38320,7 @@ const make$55 = Effect.gen(function* () {
37917
38320
  });
37918
38321
  return VcsProjectConfig.of({ resolveKind });
37919
38322
  });
37920
- const layer$45 = Layer.effect(VcsProjectConfig, make$55);
38323
+ const layer$46 = Layer.effect(VcsProjectConfig, make$56);
37921
38324
  //#endregion
37922
38325
  //#region src/vcs/VcsDriverRegistry.ts
37923
38326
  const DETECTION_CACHE_CAPACITY = 2048;
@@ -37937,7 +38340,7 @@ function parseDetectionCacheKey(key) {
37937
38340
  cwd: key.slice(separatorIndex + 1)
37938
38341
  };
37939
38342
  }
37940
- const make$54 = Effect.gen(function* () {
38343
+ const make$55 = Effect.gen(function* () {
37941
38344
  const projectConfig = yield* VcsProjectConfig;
37942
38345
  const git = yield* makeVcsDriver;
37943
38346
  const drivers = { git };
@@ -37994,7 +38397,7 @@ const make$54 = Effect.gen(function* () {
37994
38397
  resolve
37995
38398
  });
37996
38399
  });
37997
- const layer$44 = Layer.effect(VcsDriverRegistry, make$54).pipe(Layer.provide(layer$45));
38400
+ const layer$45 = Layer.effect(VcsDriverRegistry, make$55).pipe(Layer.provide(layer$46));
37998
38401
  //#endregion
37999
38402
  //#region src/checkpointing/CheckpointStore.ts
38000
38403
  /**
@@ -38014,7 +38417,7 @@ const layer$44 = Layer.effect(VcsDriverRegistry, make$54).pipe(Layer.provide(lay
38014
38417
  */
38015
38418
  /** Service tag for checkpoint persistence and restore operations. */
38016
38419
  var CheckpointStore = class extends Context.Service()("@p4code/cli/checkpointing/CheckpointStore") {};
38017
- const make$53 = Effect.gen(function* () {
38420
+ const make$54 = Effect.gen(function* () {
38018
38421
  const vcsRegistry = yield* VcsDriverRegistry;
38019
38422
  const resolveCheckpoints = Effect.fn("CheckpointStore.resolveCheckpoints")(function* (operation, cwd) {
38020
38423
  const handle = yield* vcsRegistry.resolve({ cwd });
@@ -38053,7 +38456,7 @@ const make$53 = Effect.gen(function* () {
38053
38456
  deleteCheckpointRefs
38054
38457
  });
38055
38458
  });
38056
- const layer$43 = Layer.effect(CheckpointStore, make$53);
38459
+ const layer$44 = Layer.effect(CheckpointStore, make$54);
38057
38460
  //#endregion
38058
38461
  //#region src/checkpointing/CheckpointDiffQuery.ts
38059
38462
  /**
@@ -38075,7 +38478,7 @@ function buildTurnDiffResult(input, diff) {
38075
38478
  diff
38076
38479
  };
38077
38480
  }
38078
- const make$52 = Effect.gen(function* () {
38481
+ const make$53 = Effect.gen(function* () {
38079
38482
  const projectionSnapshotQuery = yield* ProjectionSnapshotQuery;
38080
38483
  const checkpointStore = yield* CheckpointStore;
38081
38484
  const threadActivities = yield* ProjectionThreadActivityRepository;
@@ -38246,7 +38649,7 @@ const make$52 = Effect.gen(function* () {
38246
38649
  getFullThreadDiff
38247
38650
  });
38248
38651
  });
38249
- const layer$42 = Layer.effect(CheckpointDiffQuery, make$52);
38652
+ const layer$43 = Layer.effect(CheckpointDiffQuery, make$53);
38250
38653
  //#endregion
38251
38654
  //#region ../../packages/shared/src/toolCategory.ts
38252
38655
  const TOOL_CATEGORY_TITLES = {
@@ -41260,7 +41663,7 @@ function makeUpdateState(input) {
41260
41663
  output: input.output ?? null
41261
41664
  };
41262
41665
  }
41263
- const make$51 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
41666
+ const make$52 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
41264
41667
  const providerRegistry = yield* ProviderRegistry;
41265
41668
  const spawner = yield* ChildProcessSpawner.ChildProcessSpawner;
41266
41669
  const httpClient = yield* HttpClient.HttpClient;
@@ -41375,7 +41778,7 @@ const make$51 = Effect.fn("ProviderMaintenanceRunner.make")(function* () {
41375
41778
  });
41376
41779
  return ProviderMaintenanceRunner.of({ updateProvider });
41377
41780
  });
41378
- const layer$41 = Layer.effect(ProviderMaintenanceRunner, make$51());
41781
+ const layer$42 = Layer.effect(ProviderMaintenanceRunner, make$52());
41379
41782
  //#endregion
41380
41783
  //#region src/provider/Services/ProviderInstanceRegistry.ts
41381
41784
  var ProviderInstanceRegistry = class extends Context.Service()("@p4code/cli/provider/Services/ProviderInstanceRegistry") {};
@@ -41399,11 +41802,11 @@ const makeTextGenerationFromRegistry = (registry) => TextGeneration.of({
41399
41802
  detail: "This provider does not report account usage."
41400
41803
  }))))
41401
41804
  });
41402
- const make$50 = Effect.gen(function* () {
41805
+ const make$51 = Effect.gen(function* () {
41403
41806
  const registry = yield* ProviderInstanceRegistry;
41404
41807
  return makeTextGenerationFromRegistry(registry);
41405
41808
  });
41406
- const layer$40 = Layer.effect(TextGeneration, make$50);
41809
+ const layer$41 = Layer.effect(TextGeneration, make$51);
41407
41810
  //#endregion
41408
41811
  //#region src/provider/Drivers/ClaudeHome.ts
41409
41812
  const resolveClaudeHomePath = Effect.fn("resolveClaudeHomePath")(function* (config) {
@@ -42395,7 +42798,7 @@ Layer.succeed(UsageService, UsageService.of({ readSummary: (input) => Effect.suc
42395
42798
  },
42396
42799
  scanDurationMs: 0
42397
42800
  }) }));
42398
- const make$49 = Effect.gen(function* () {
42801
+ const make$50 = Effect.gen(function* () {
42399
42802
  const fileSystem = yield* FileSystem.FileSystem;
42400
42803
  const path = yield* Path.Path;
42401
42804
  const config = yield* ServerConfig$1;
@@ -42627,7 +43030,302 @@ const make$49 = Effect.gen(function* () {
42627
43030
  };
42628
43031
  }) };
42629
43032
  });
42630
- const layer$39 = Layer.effect(UsageService, make$49);
43033
+ const layer$40 = Layer.effect(UsageService, make$50);
43034
+ //#endregion
43035
+ //#region src/feed/ArticleText.ts
43036
+ const BLOCK_TAGS = /<\/?(?:p|div|article|section|main|h[1-6]|li|br)[^>]*>/gi;
43037
+ function extractReadableArticleText(html) {
43038
+ const text = html.replace(/<script\b[^>]*>[\s\S]*?<\/script>/gi, " ").replace(/<style\b[^>]*>[\s\S]*?<\/style>/gi, " ").replace(BLOCK_TAGS, "\n").replace(/<[^>]+>/g, " ").replaceAll("&nbsp;", " ").replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replace(/[ \t]+/g, " ").replace(/\n\s*\n+/g, "\n").trim();
43039
+ return text.length >= 160 ? text : null;
43040
+ }
43041
+ function hackerNewsEngagementBand(points, comments) {
43042
+ if (points >= 300 || comments >= 100) return "high";
43043
+ if (points >= 100 || comments >= 40) return "medium";
43044
+ return "low";
43045
+ }
43046
+ function hackerNewsDiscussionUrl(id) {
43047
+ return `https://news.ycombinator.com/item?id=${encodeURIComponent(id)}`;
43048
+ }
43049
+ function hackerNewsItemId(discussionUrl) {
43050
+ if (discussionUrl === null) return null;
43051
+ try {
43052
+ return new URL(discussionUrl).searchParams.get("id");
43053
+ } catch {
43054
+ return null;
43055
+ }
43056
+ }
43057
+ //#endregion
43058
+ //#region src/feed/SyndicationSource.ts
43059
+ const decodeEntities = (value) => value.replaceAll("<![CDATA[", "").replaceAll("]]>", "").replaceAll("&amp;", "&").replaceAll("&lt;", "<").replaceAll("&gt;", ">").replaceAll("&quot;", "\"").replaceAll("&#39;", "'").trim();
43060
+ const tag = (xml, names) => {
43061
+ for (const name of names) {
43062
+ const match = xml.match(new RegExp(`<${name}(?:\\s[^>]*)?>([\\s\\S]*?)<\\/${name}>`, "i"));
43063
+ if (match?.[1]) return decodeEntities(match[1]);
43064
+ }
43065
+ return null;
43066
+ };
43067
+ function canonicalizeArticleUrl(value) {
43068
+ const url = new URL(value);
43069
+ url.hash = "";
43070
+ for (const key of [...url.searchParams.keys()]) if (key.startsWith("utm_") || key === "ref" || key === "source") url.searchParams.delete(key);
43071
+ url.searchParams.sort();
43072
+ return url.toString();
43073
+ }
43074
+ function parseSyndicationFeed(xml) {
43075
+ return (xml.match(/<(?:item|entry)(?:\s[^>]*)?>[\s\S]*?<\/(?:item|entry)>/gi) ?? []).flatMap((block) => {
43076
+ const atomLink = block.match(/<link\b[^>]*href=["']([^"']+)["'][^>]*>/i)?.[1] ?? null;
43077
+ const rawUrl = tag(block, [
43078
+ "link",
43079
+ "guid",
43080
+ "id"
43081
+ ]);
43082
+ const title = tag(block, ["title"]);
43083
+ const url = atomLink ?? rawUrl;
43084
+ if (!title || !url) return [];
43085
+ let canonicalUrl;
43086
+ try {
43087
+ canonicalUrl = canonicalizeArticleUrl(url);
43088
+ } catch {
43089
+ return [];
43090
+ }
43091
+ const date = tag(block, [
43092
+ "pubDate",
43093
+ "published",
43094
+ "updated"
43095
+ ]);
43096
+ const parsedDate = date === null ? NaN : Date.parse(date);
43097
+ return [{
43098
+ title,
43099
+ url: canonicalUrl,
43100
+ author: tag(block, [
43101
+ "dc:creator",
43102
+ "author",
43103
+ "name"
43104
+ ]),
43105
+ publishedAt: Number.isNaN(parsedDate) ? (/* @__PURE__ */ new Date(0)).toISOString() : new Date(parsedDate).toISOString(),
43106
+ content: tag(block, [
43107
+ "content:encoded",
43108
+ "content",
43109
+ "description",
43110
+ "summary"
43111
+ ]),
43112
+ discussionUrl: tag(block, ["comments"])
43113
+ }];
43114
+ });
43115
+ }
43116
+ //#endregion
43117
+ //#region src/feed/FeedService.ts
43118
+ const FEED_REQUEST_TIMEOUT_MS = 2e4;
43119
+ const FEED_REFRESH_LEASE_MS = 5 * 6e4;
43120
+ const FEED_FETCH_CONCURRENCY = 4;
43121
+ const FEED_MODEL = "gpt-5.6-luna";
43122
+ const FEED_FALLBACK_MODEL = "claude-sonnet-5";
43123
+ const fail = (code, message) => new FeedError({
43124
+ code,
43125
+ message
43126
+ });
43127
+ const jsonRequest = Effect.fn("FeedService.jsonRequest")(function* (url, token, init) {
43128
+ const response = yield* Effect.tryPromise({
43129
+ try: (signal) => fetch(url, {
43130
+ ...init,
43131
+ signal,
43132
+ headers: {
43133
+ authorization: `Bearer ${token}`,
43134
+ accept: "application/json",
43135
+ "content-type": "application/json",
43136
+ ...init?.headers
43137
+ }
43138
+ }),
43139
+ catch: () => fail("hub_unavailable", "Hub is unavailable.")
43140
+ }).pipe(Effect.timeout(FEED_REQUEST_TIMEOUT_MS), Effect.mapError(() => fail("hub_unavailable", "Hub request timed out.")));
43141
+ if (!response.ok) return yield* fail("hub_unavailable", `Hub returned status ${response.status}.`);
43142
+ if (response.status === 204) return {};
43143
+ return yield* Effect.tryPromise({
43144
+ try: () => response.json(),
43145
+ catch: () => fail("hub_unavailable", "Hub returned invalid JSON.")
43146
+ });
43147
+ });
43148
+ const make$49 = Effect.gen(function* () {
43149
+ const hubLink = yield* HubLink;
43150
+ const providers = yield* ProviderInstanceRegistry;
43151
+ const settings = Effect.fn("FeedService.settings")(function* () {
43152
+ const state = yield* hubLink.current;
43153
+ if (Option.isNone(state.settings)) return yield* fail("hub_unavailable", "Connect this environment to Hub to use Feed.");
43154
+ return state.settings.value;
43155
+ });
43156
+ const call = Effect.fn("FeedService.call")(function* (path, init) {
43157
+ const linked = yield* settings();
43158
+ return yield* jsonRequest(`${linked.baseUrl}${path}`, linked.token, init);
43159
+ });
43160
+ const sources = () => call("/feed/sources");
43161
+ return {
43162
+ list: Effect.fn("FeedService.list")(function* (input) {
43163
+ const result = yield* call("/feed/articles");
43164
+ const query = input.query?.trim().toLocaleLowerCase();
43165
+ const articles = result.articles.filter((article) => input.sourceId === void 0 || article.sourceId === input.sourceId).filter((article) => !input.unreadOnly || article.readAt === null).filter((article) => input.startDate === void 0 || article.publishedAt >= input.startDate).filter((article) => input.endDate === void 0 || article.publishedAt <= input.endDate).filter((article) => !query || `${article.title}\n${article.summary?.summary ?? ""}\n${article.summary?.highlights.join(" ") ?? ""}`.toLocaleLowerCase().includes(query)).toSorted((a, b) => input.sort === "oldest" ? a.publishedAt.localeCompare(b.publishedAt) : b.publishedAt.localeCompare(a.publishedAt));
43166
+ return {
43167
+ ...result,
43168
+ articles
43169
+ };
43170
+ }),
43171
+ refresh: Effect.fn("FeedService.refresh")(function* () {
43172
+ const owner = crypto.randomUUID();
43173
+ const refreshedAt = (/* @__PURE__ */ new Date()).toISOString();
43174
+ if (!(yield* call("/feed/lease", {
43175
+ method: "POST",
43176
+ body: JSON.stringify({
43177
+ owner,
43178
+ expiresAt: new Date(Date.now() + FEED_REFRESH_LEASE_MS).toISOString()
43179
+ })
43180
+ })).acquired) return {
43181
+ fetched: 0,
43182
+ summarized: 0,
43183
+ failedSources: [],
43184
+ refreshedAt
43185
+ };
43186
+ const existing = yield* call("/feed/articles");
43187
+ const existingByUrl = new Map(existing.articles.map((article) => [article.canonicalUrl, article]));
43188
+ const enabled = (yield* sources()).filter((source) => source.enabled);
43189
+ let fetched = 0;
43190
+ let summarized = 0;
43191
+ const failedSources = [];
43192
+ yield* Effect.forEach(enabled, (source) => Effect.gen(function* () {
43193
+ const entries = parseSyndicationFeed(yield* Effect.tryPromise({
43194
+ try: () => fetch(source.feedUrl).then((response) => {
43195
+ if (!response.ok) throw new Error(String(response.status));
43196
+ return response.text();
43197
+ }),
43198
+ catch: () => fail("fetch_failed", `Could not fetch ${source.name}.`)
43199
+ }));
43200
+ for (const entry of entries) {
43201
+ const current = existingByUrl.get(entry.url);
43202
+ let contentText = entry.content ? extractReadableArticleText(entry.content) : null;
43203
+ if (contentText === null) contentText = yield* Effect.tryPromise({
43204
+ try: () => fetch(entry.url).then((response) => response.ok ? response.text() : "").then(extractReadableArticleText),
43205
+ catch: () => null
43206
+ });
43207
+ const revision = contentText ?? `${entry.title}:${entry.publishedAt}`;
43208
+ if (current?.contentText === contentText && current.summary !== null) continue;
43209
+ const id = current?.id ?? FeedArticleId.make(crypto.randomUUID());
43210
+ const hnId = source.kind === "hacker_news" ? hackerNewsItemId(entry.discussionUrl) : null;
43211
+ const hnEngagement = hnId === null ? null : yield* Effect.tryPromise({
43212
+ try: () => fetch(`https://hacker-news.firebaseio.com/v0/item/${encodeURIComponent(hnId)}.json`).then((response) => response.ok ? response.json() : null),
43213
+ catch: () => null
43214
+ });
43215
+ let summary = null;
43216
+ let status = "summary_unavailable";
43217
+ if (contentText !== null) {
43218
+ const instances = yield* providers.listInstances;
43219
+ const candidates = [{
43220
+ instance: instances.find((instance) => instance.driverKind === "codex" && instance.enabled),
43221
+ model: FEED_MODEL
43222
+ }, {
43223
+ instance: instances.find((instance) => instance.driverKind === "claudeAgent" && instance.enabled),
43224
+ model: FEED_FALLBACK_MODEL
43225
+ }];
43226
+ for (const candidate of candidates) {
43227
+ if (!candidate.instance) continue;
43228
+ const generated = yield* candidate.instance.textGeneration.generatePrContent({
43229
+ cwd: process.cwd(),
43230
+ baseBranch: "feed",
43231
+ headBranch: "article",
43232
+ commitSummary: entry.title,
43233
+ diffSummary: "Summarize this article for a dense technology news feed. Return concise summary in body.",
43234
+ diffPatch: contentText.slice(0, 24e3),
43235
+ modelSelection: {
43236
+ instanceId: ProviderInstanceId.make(candidate.instance.instanceId),
43237
+ model: candidate.model
43238
+ }
43239
+ }).pipe(Effect.option);
43240
+ if (Option.isNone(generated)) continue;
43241
+ const body = generated.value.body.trim();
43242
+ summary = {
43243
+ modelSelection: `${candidate.instance.instanceId}:${candidate.model}`,
43244
+ summary: body,
43245
+ highlights: body.split(/(?<=[.!?])\s+/).filter(Boolean).slice(0, 3),
43246
+ references: [entry.url],
43247
+ summarizedAt: refreshedAt
43248
+ };
43249
+ status = "ready";
43250
+ summarized += 1;
43251
+ break;
43252
+ }
43253
+ if (summary === null) status = "summary_failed";
43254
+ }
43255
+ yield* call(`/feed/articles/${encodeURIComponent(id)}`, {
43256
+ method: "PUT",
43257
+ body: JSON.stringify({
43258
+ sourceId: source.id,
43259
+ canonicalUrl: entry.url,
43260
+ discussionUrl: hnId ? hackerNewsDiscussionUrl(hnId) : null,
43261
+ title: entry.title,
43262
+ author: entry.author,
43263
+ publishedAt: entry.publishedAt,
43264
+ fetchedAt: refreshedAt,
43265
+ contentText,
43266
+ status,
43267
+ contentRevision: revision,
43268
+ summary,
43269
+ engagement: hnEngagement === null ? {
43270
+ points: null,
43271
+ comments: null,
43272
+ band: "unknown",
43273
+ observedAt: refreshedAt
43274
+ } : {
43275
+ points: hnEngagement.score ?? 0,
43276
+ comments: hnEngagement.descendants ?? 0,
43277
+ band: hackerNewsEngagementBand(hnEngagement.score ?? 0, hnEngagement.descendants ?? 0),
43278
+ observedAt: refreshedAt
43279
+ }
43280
+ })
43281
+ });
43282
+ fetched += 1;
43283
+ }
43284
+ }).pipe(Effect.catch(() => Effect.sync(() => {
43285
+ failedSources.push(source.name);
43286
+ }))), { concurrency: FEED_FETCH_CONCURRENCY });
43287
+ yield* call("/feed/refreshed-at", {
43288
+ method: "PUT",
43289
+ body: JSON.stringify({ refreshedAt })
43290
+ });
43291
+ yield* call("/feed/lease", {
43292
+ method: "DELETE",
43293
+ body: JSON.stringify({ owner })
43294
+ });
43295
+ return {
43296
+ fetched,
43297
+ summarized,
43298
+ failedSources,
43299
+ refreshedAt
43300
+ };
43301
+ }),
43302
+ sources,
43303
+ upsertSource: (input) => call("/feed/sources", {
43304
+ method: "PUT",
43305
+ body: JSON.stringify(input)
43306
+ }),
43307
+ deleteSource: (input) => call(`/feed/sources/${encodeURIComponent(input.sourceId)}`, { method: "DELETE" }),
43308
+ markRead: (input) => call("/feed/read", {
43309
+ method: "PUT",
43310
+ body: JSON.stringify(input)
43311
+ }),
43312
+ cleanup: (input) => call("/feed/cleanup", {
43313
+ method: "POST",
43314
+ body: JSON.stringify(input)
43315
+ })
43316
+ };
43317
+ });
43318
+ const unavailable = () => Effect.fail(fail("hub_unavailable", "Feed service is unavailable."));
43319
+ var FeedService = class extends Context.Reference("@p4code/cli/feed/FeedService", { defaultValue: () => ({
43320
+ list: unavailable,
43321
+ refresh: unavailable,
43322
+ sources: unavailable,
43323
+ upsertSource: unavailable,
43324
+ deleteSource: unavailable,
43325
+ markRead: unavailable,
43326
+ cleanup: unavailable
43327
+ }) }) {};
43328
+ const layer$39 = Layer.effect(FeedService, make$49);
42631
43329
  const SKILL_MANIFEST_FILENAME = "SKILL.md";
42632
43330
  /**
42633
43331
  * Split a catalogue id (`owner/repo/skill-name`) into its parts.
@@ -44934,7 +45632,7 @@ const makeWithOptions$1 = Effect.fn("TerminalManager.makeWithOptions")(function*
44934
45632
  subscribeMetadata
44935
45633
  });
44936
45634
  });
44937
- const layer$36 = Layer.effect(TerminalManager, make$46()).pipe(Layer.provide(layer$61));
45635
+ const layer$36 = Layer.effect(TerminalManager, make$46()).pipe(Layer.provide(layer$62));
44938
45636
  //#endregion
44939
45637
  //#region src/mcp/McpInvocationContext.ts
44940
45638
  var McpInvocationContext = class extends Context.Service()("@p4code/cli/mcp/McpInvocationContext") {};
@@ -59624,6 +60322,13 @@ const RPC_REQUIRED_SCOPE = /* @__PURE__ */ new Map([
59624
60322
  [WS_METHODS.tasksUpdate, AuthOrchestrationOperateScope],
59625
60323
  [WS_METHODS.tasksDelete, AuthOrchestrationOperateScope],
59626
60324
  [WS_METHODS.tasksStartThread, AuthOrchestrationOperateScope],
60325
+ [WS_METHODS.feedList, AuthOrchestrationReadScope],
60326
+ [WS_METHODS.feedRefresh, AuthOrchestrationReadScope],
60327
+ [WS_METHODS.feedSourcesList, AuthOrchestrationReadScope],
60328
+ [WS_METHODS.feedSourcesUpsert, AuthOrchestrationOperateScope],
60329
+ [WS_METHODS.feedSourcesDelete, AuthOrchestrationOperateScope],
60330
+ [WS_METHODS.feedMarkRead, AuthOrchestrationOperateScope],
60331
+ [WS_METHODS.feedCleanup, AuthOrchestrationOperateScope],
59627
60332
  [WS_METHODS.subscribeTasks, AuthOrchestrationReadScope],
59628
60333
  [WS_METHODS.hubGetSyncStatus, AuthOrchestrationReadScope],
59629
60334
  [WS_METHODS.hubConnect, AuthOrchestrationOperateScope],
@@ -59799,6 +60504,7 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
59799
60504
  const linearClient = yield* LinearClient;
59800
60505
  const claudeMcpFiles = yield* ClaudeMcpFiles;
59801
60506
  const skillRegistry = yield* SkillRegistry;
60507
+ const feed = yield* FeedService;
59802
60508
  const listMcpServersEverywhere = Effect.gen(function* () {
59803
60509
  const servers = [...yield* mcpRegistry.list];
59804
60510
  const projectRows = yield* projectionProjects.listAll().pipe(Effect.map((rows) => rows.filter((row) => row.deletedAt === null)), Effect.orElseSucceed(() => []));
@@ -60379,6 +61085,13 @@ const makeWsRpcLayer = (currentSession, previewAutomationBroker) => WsRpcGroup.t
60379
61085
  };
60380
61086
  }), { "rpc.aggregate": "tasks" }),
60381
61087
  [WS_METHODS.subscribeTasks]: ({ source }) => observeRpcStreamEffect$1(WS_METHODS.subscribeTasks, Effect.succeed(taskRepositories.forSource(source).streamWithSnapshot.pipe(Stream.catch((cause) => Stream.fromEffect(toTaskStoreError("tasks.subscribe")(cause))))), { "rpc.aggregate": "tasks" }),
61088
+ [WS_METHODS.feedList]: (input) => observeRpcEffect$1(WS_METHODS.feedList, feed.list(input), { "rpc.aggregate": "feed" }),
61089
+ [WS_METHODS.feedRefresh]: () => observeRpcEffect$1(WS_METHODS.feedRefresh, feed.refresh(), { "rpc.aggregate": "feed" }),
61090
+ [WS_METHODS.feedSourcesList]: () => observeRpcEffect$1(WS_METHODS.feedSourcesList, feed.sources(), { "rpc.aggregate": "feed" }),
61091
+ [WS_METHODS.feedSourcesUpsert]: (input) => observeRpcEffect$1(WS_METHODS.feedSourcesUpsert, feed.upsertSource(input), { "rpc.aggregate": "feed" }),
61092
+ [WS_METHODS.feedSourcesDelete]: (input) => observeRpcEffect$1(WS_METHODS.feedSourcesDelete, feed.deleteSource(input).pipe(Effect.as({})), { "rpc.aggregate": "feed" }),
61093
+ [WS_METHODS.feedMarkRead]: (input) => observeRpcEffect$1(WS_METHODS.feedMarkRead, feed.markRead(input).pipe(Effect.as({})), { "rpc.aggregate": "feed" }),
61094
+ [WS_METHODS.feedCleanup]: (input) => observeRpcEffect$1(WS_METHODS.feedCleanup, feed.cleanup(input), { "rpc.aggregate": "feed" }),
60382
61095
  [WS_METHODS.hubGetSyncStatus]: (_input) => observeRpcEffect$1(WS_METHODS.hubGetSyncStatus, assetSync.status, { "rpc.aggregate": "hub" }),
60383
61096
  [WS_METHODS.hubConnect]: (input) => observeRpcEffect$1(WS_METHODS.hubConnect, hubLink.connect(input).pipe(Effect.mapError((cause) => new HubLinkError({ detail: cause.message })), Effect.andThen(assetSync.status)), { "rpc.aggregate": "hub" }),
60384
61097
  [WS_METHODS.hubDisconnect]: (_input) => observeRpcEffect$1(WS_METHODS.hubDisconnect, hubLink.disconnect.pipe(Effect.mapError((cause) => new HubLinkError({ detail: cause.message })), Effect.andThen(assetSync.status)), { "rpc.aggregate": "hub" }),
@@ -60671,7 +61384,7 @@ const websocketRpcRouteLayer = Layer.unwrap(Effect.gen(function* () {
60671
61384
  const serverAuth = yield* EnvironmentAuth;
60672
61385
  const sessions = yield* SessionStore;
60673
61386
  const session = yield* serverAuth.authenticateWebSocketUpgrade(request).pipe(Effect.catchIf(isServerAuthCredentialError, (error) => failEnvironmentAuthInvalid(serverAuthCredentialReason(error))), Effect.catchIf(isServerAuthInternalError, (error) => failEnvironmentInternal("internal_error", error)));
60674
- const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$41), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(PullRequestService, pullRequests)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$6.pipe(Layer.provide(layer$21.pipe(Layer.provide(Layer.mergeAll(layer$29, layer$27, layer$25, layer$23)), Layer.provideMerge(layer$46), Layer.provide(layer$44.pipe(Layer.provide(layer$45))))), Layer.provide(layer$47))))));
61387
+ const rpcWebSocketHttpEffect = yield* RpcServer.toHttpEffectWebsocket(WsRpcGroup, { disableTracing: true }).pipe(Effect.provide(makeWsRpcLayer(session, previewAutomationBroker).pipe(Layer.provideMerge(RpcSerialization.layerJson), Layer.provide(layer$42), Layer.provide(Layer.succeed(ServerSelfUpdate, serverSelfUpdate)), Layer.provide(Layer.succeed(PullRequestService, pullRequests)), Layer.provide(Layer.succeed(TaskRepositoryRegistry, taskRepositories)), Layer.provide(Layer.succeed(ProjectionProjectRepository, projectionProjects)), Layer.provide(Layer.succeed(P4ProjectFileLoader, p4ProjectFileLoader)), Layer.provide(layer$6.pipe(Layer.provide(layer$21.pipe(Layer.provide(Layer.mergeAll(layer$29, layer$27, layer$25, layer$23)), Layer.provideMerge(layer$47), Layer.provide(layer$45.pipe(Layer.provide(layer$46))))), Layer.provide(layer$48))))));
60675
61388
  return yield* Effect.acquireUseRelease(sessions.markConnected(session.sessionId), () => rpcWebSocketHttpEffect, () => sessions.markDisconnected(session.sessionId));
60676
61389
  }).pipe(Effect.catchTags({
60677
61390
  EnvironmentAuthInvalidError: HttpServerRespondable.toResponse,
@@ -62809,7 +63522,7 @@ const makeOpenCodeRuntime = Effect.gen(function* () {
62809
63522
  };
62810
63523
  });
62811
63524
  var OpenCodeRuntime = class extends Context.Service()("@p4code/cli/provider/opencodeRuntime") {};
62812
- const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$79));
63525
+ const OpenCodeRuntimeLive = Layer.effect(OpenCodeRuntime, makeOpenCodeRuntime).pipe(Layer.provide(layer$80));
62813
63526
  //#endregion
62814
63527
  //#region src/textGeneration/TextGenerationUtils.ts
62815
63528
  const isTextGenerationError$3 = Schema$1.is(TextGenerationError);
@@ -104429,7 +105142,7 @@ const ObservabilityLive = Layer.unwrap(Effect.gen(function* () {
104429
105142
  sink,
104430
105143
  ...delegate ? { delegate } : {}
104431
105144
  });
104432
- return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$48(sink));
105145
+ return Layer.mergeAll(Layer.succeed(Tracer.Tracer, tracer), layer$49(sink));
104433
105146
  })).pipe(Layer.provide(OtlpExporter.layerFlusher), Layer.provideMerge(otlpSerializationLayer));
104434
105147
  const metricsLayer = config.otlpMetricsUrl === void 0 ? Layer.empty : OtlpMetrics.layer({
104435
105148
  url: config.otlpMetricsUrl,
@@ -104730,27 +105443,27 @@ const ReactorLayerLive = Layer.empty.pipe(Layer.provideMerge(OrchestrationReacto
104730
105443
  const ProviderSessionDirectoryLayerLive = ProviderSessionDirectoryLive.pipe(Layer.provide(layer$4));
104731
105444
  const ProviderLayerLive = ProviderServiceLive.pipe(Layer.provide(ProviderAdapterRegistryLive), Layer.provideMerge(ProviderSessionDirectoryLayerLive));
104732
105445
  const PersistenceLayerLive = Layer.empty.pipe(Layer.provideMerge(layerConfig));
104733
- const VcsDriverRegistryLayerLive = layer$44.pipe(Layer.provide(layer$45));
104734
- const SourceControlProviderRegistryLayerLive = layer$21.pipe(Layer.provide(Layer.mergeAll(layer$29, layer$27, layer$25, layer$23)), Layer.provideMerge(layer$46), Layer.provideMerge(VcsDriverRegistryLayerLive));
104735
- const GitManagerLayerLive = layer$20.pipe(Layer.provideMerge(layer$30), Layer.provideMerge(layer$46), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$40));
104736
- const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$46));
105446
+ const VcsDriverRegistryLayerLive = layer$45.pipe(Layer.provide(layer$46));
105447
+ const SourceControlProviderRegistryLayerLive = layer$21.pipe(Layer.provide(Layer.mergeAll(layer$29, layer$27, layer$25, layer$23)), Layer.provideMerge(layer$47), Layer.provideMerge(VcsDriverRegistryLayerLive));
105448
+ const GitManagerLayerLive = layer$20.pipe(Layer.provideMerge(layer$30), Layer.provideMerge(layer$47), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(layer$41));
105449
+ const GitLayerLive = Layer.empty.pipe(Layer.provideMerge(GitManagerLayerLive), Layer.provideMerge(layer$47));
104737
105450
  const GitWorkflowLayerLive = layer$19.pipe(Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(GitLayerLive));
104738
- const SourceControlRepositoryServiceLayerLive = layer$5.pipe(Layer.provideMerge(layer$46), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
104739
- const ReviewLayerLive = layer$16.pipe(Layer.provideMerge(layer$46), Layer.provideMerge(VcsDriverRegistryLayerLive));
104740
- const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$45), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$17.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$18.pipe(Layer.provide(GitWorkflowLayerLive))));
104741
- const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$42), Layer.provideMerge(layer$43.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
104742
- const PortScannerLayerLive = layer$37.pipe(Layer.provide(layer$61));
105451
+ const SourceControlRepositoryServiceLayerLive = layer$5.pipe(Layer.provideMerge(layer$47), Layer.provideMerge(SourceControlProviderRegistryLayerLive));
105452
+ const ReviewLayerLive = layer$16.pipe(Layer.provideMerge(layer$47), Layer.provideMerge(VcsDriverRegistryLayerLive));
105453
+ const VcsLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$46), Layer.provideMerge(VcsDriverRegistryLayerLive), Layer.provideMerge(layer$17.pipe(Layer.provide(VcsDriverRegistryLayerLive))), Layer.provideMerge(GitWorkflowLayerLive), Layer.provideMerge(ReviewLayerLive), Layer.provideMerge(SourceControlRepositoryServiceLayerLive), Layer.provideMerge(layer$18.pipe(Layer.provide(GitWorkflowLayerLive))));
105454
+ const CheckpointingLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$43), Layer.provideMerge(layer$44.pipe(Layer.provide(VcsDriverRegistryLayerLive))));
105455
+ const PortScannerLayerLive = layer$37.pipe(Layer.provide(layer$62));
104743
105456
  const TerminalLayerLive = layer$36.pipe(Layer.provide(PtyAdapterLive), Layer.provide(PortScannerLayerLive));
104744
105457
  const PreviewLayerLive = Layer.empty.pipe(Layer.provideMerge(layer$34), Layer.provideMerge(PortScannerLayerLive));
104745
- const WorkspaceEntriesLayerLive = layer$32.pipe(Layer.provide(layer$51));
104746
- const WorkspaceFileSystemLayerLive = layer$31.pipe(Layer.provide(layer$51), Layer.provide(WorkspaceEntriesLayerLive));
104747
- const WorkspaceLayerLive = Layer.mergeAll(layer$51, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
104748
- const ProjectFaviconResolverLayerLive = layer$49.pipe(Layer.provide(layer$51), Layer.provide(layer$50));
104749
- const AuthLayerLive = layer$71.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$75));
105458
+ const WorkspaceEntriesLayerLive = layer$32.pipe(Layer.provide(layer$52));
105459
+ const WorkspaceFileSystemLayerLive = layer$31.pipe(Layer.provide(layer$52), Layer.provide(WorkspaceEntriesLayerLive));
105460
+ const WorkspaceLayerLive = Layer.mergeAll(layer$52, WorkspaceEntriesLayerLive, WorkspaceFileSystemLayerLive);
105461
+ const ProjectFaviconResolverLayerLive = layer$50.pipe(Layer.provide(layer$52), Layer.provide(layer$51));
105462
+ const AuthLayerLive = layer$72.pipe(Layer.provideMerge(PersistenceLayerLive), Layer.provide(layer$76));
104750
105463
  const ProviderRuntimeLayerLive = ProviderSessionReaperLive.pipe(Layer.provideMerge(ProviderLayerLive), Layer.provideMerge(OrchestrationLayerLive));
104751
- const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$64)), Layer.provideMerge(layer$59), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$68.pipe(Layer.provide(layer$75))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$60), Layer.provideMerge(layer$53), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$1.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$65, layer$38).pipe(Layer.provideMerge(layer$66), Layer.provideMerge(layer$67))))), Layer.provideMerge(layer$75));
104752
- const UsageLayerLive = layer$39.pipe(Layer.provide(layer$68.pipe(Layer.provide(layer$75))));
104753
- const RuntimeDependenciesLive = RuntimeCoreDependenciesLive.pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$15), Layer.provideMerge(layer$14), Layer.provideMerge(layer$13), Layer.provideMerge(layer$56), Layer.provideMerge(layer$58), Layer.provideMerge(layer$57), Layer.provide(layer$79));
105464
+ const RuntimeCoreDependenciesLive = ReactorLayerLive.pipe(Layer.provideMerge(CheckpointingLayerLive), Layer.provideMerge(SourceControlProviderRegistryLayerLive), Layer.provideMerge(GitLayerLive), Layer.provideMerge(VcsLayerLive), Layer.provideMerge(ProviderRuntimeLayerLive), Layer.provideMerge(Layer.mergeAll(TerminalLayerLive, PreviewLayerLive, RoutedTaskRepositoryLive)), Layer.provideMerge(Layer.mergeAll(PersistenceLayerLive, layer$65)), Layer.provideMerge(layer$60), Layer.provideMerge(ProviderRegistryLive), Layer.provideMerge(ProviderInstanceRegistryHydrationLive), Layer.provideMerge(ProviderEventLoggersLive), Layer.provideMerge(OpenCodeRuntimeLive), Layer.provideMerge(layer$69.pipe(Layer.provide(layer$76))), Layer.provideMerge(WorkspaceLayerLive), Layer.provideMerge(ProjectFaviconResolverLayerLive), Layer.provideMerge(layer$61), Layer.provideMerge(layer$54), Layer.provideMerge(AuthLayerLive), Layer.provideMerge(layer$1.pipe(Layer.provideMerge(LinearClientLive), Layer.provideMerge(Layer.mergeAll(LinearMcpClientLive, TrackerSecretsLive)), Layer.provideMerge(Layer.mergeAll(layer$66, layer$38).pipe(Layer.provideMerge(layer$67), Layer.provideMerge(layer$68))))), Layer.provideMerge(layer$76));
105465
+ const UsageLayerLive = layer$40.pipe(Layer.provide(layer$69.pipe(Layer.provide(layer$76))));
105466
+ const RuntimeDependenciesLive = layer$39.pipe(Layer.provideMerge(RuntimeCoreDependenciesLive)).pipe(Layer.provideMerge(UsageLayerLive), Layer.provideMerge(layer$15), Layer.provideMerge(layer$14), Layer.provideMerge(layer$13), Layer.provideMerge(layer$57), Layer.provideMerge(layer$59), Layer.provideMerge(layer$58), Layer.provide(layer$80));
104754
105467
  /**
104755
105468
  * Hub asset sync.
104756
105469
  *
@@ -104758,10 +105471,10 @@ const RuntimeDependenciesLive = RuntimeCoreDependenciesLive.pipe(Layer.provideMe
104758
105471
  * not-configured shape, and every call reports that rather than failing — so
104759
105472
  * this costs a server with no hub nothing but a layer.
104760
105473
  */
104761
- const AssetSyncLive = layer$62.pipe(Layer.provideMerge(layer$63), Layer.provideMerge(layer$64));
104762
- const RuntimeServicesLive = layer$52.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
104763
- const PullRequestServiceLive = layer$7.pipe(Layer.provide(layer$8), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(layer$47));
104764
- const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(pullRequestHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$3))).pipe(Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$50), Layer.provide(PullRequestServiceLive), Layer.provide(layer$35), Layer.provide(layer$54), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
105474
+ const AssetSyncLive = layer$63.pipe(Layer.provideMerge(layer$64), Layer.provideMerge(layer$65));
105475
+ const RuntimeServicesLive = layer$53.pipe(Layer.provideMerge(AssetSyncLive), Layer.provideMerge(RuntimeDependenciesLive));
105476
+ const PullRequestServiceLive = layer$7.pipe(Layer.provide(layer$8), Layer.provide(SourceControlProviderRegistryLayerLive), Layer.provide(layer$48));
105477
+ const makeRoutesLayer = Layer.mergeAll(Layer.mergeAll(HttpApiBuilder.layer(EnvironmentHttpApi).pipe(Layer.provide(authHttpApiLayer), Layer.provide(orchestrationHttpApiLayer), Layer.provide(pullRequestHttpApiLayer), Layer.provide(serverEnvironmentHttpApiLayer), Layer.provide(environmentAuthenticatedAuthLayer)), otlpTracesProxyRouteLayer, assetRouteLayer, mcpOAuthCallbackRouteLayer, staticAndDevRouteLayer, websocketRpcRouteLayer), layer.pipe(Layer.provide(layer$3))).pipe(Layer.provide(ProjectionProjectRepositoryLive.pipe(Layer.provide(PersistenceLayerLive))), Layer.provide(layer$51), Layer.provide(PullRequestServiceLive), Layer.provide(layer$35), Layer.provide(layer$55), Layer.provide(browserApiCorsLayer), Layer.provide(httpCompressionLayer));
104765
105478
  const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
104766
105479
  const config = yield* ServerConfig$1;
104767
105480
  yield* fixPath();
@@ -104804,7 +105517,7 @@ const makeServerLayer = Layer.unwrap(Effect.gen(function* () {
104804
105517
  cause,
104805
105518
  servePort: configured.servePort
104806
105519
  }))) : Effect.void)) : Layer.empty;
104807
- return Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$47), Layer.provideMerge(PlatformServicesLive));
105520
+ return Layer.mergeAll(HttpRouter.serve(makeRoutesLayer, { disableLogger: !config.logWebSocketEvents }), httpListeningLayer, runtimeStateLayer, tailscaleServeLayer).pipe(Layer.provideMerge(RuntimeServicesLive), Layer.provideMerge(HttpResponseCompressionLive), Layer.provideMerge(HttpServerLive), Layer.provide(ObservabilityLive), Layer.provideMerge(FetchHttpClient.layer), Layer.provideMerge(layer$48), Layer.provideMerge(PlatformServicesLive));
104808
105521
  }));
104809
105522
  const runServer = Layer.launch(makeServerLayer);
104810
105523
  //#endregion
@@ -105102,11 +105815,11 @@ function describeServiceUpdateState(state) {
105102
105815
  //#endregion
105103
105816
  //#region src/cli/service.ts
105104
105817
  const isBootServiceCommandError = Schema$1.is(BootServiceCommandError);
105105
- const bootServiceLayer = (config) => layer$55({
105818
+ const bootServiceLayer = (config) => layer$56({
105106
105819
  baseDir: config.baseDir,
105107
105820
  logsDir: config.logsDir,
105108
105821
  cliVersion: version
105109
- }).pipe(Layer.provide(layer$61));
105822
+ }).pipe(Layer.provide(layer$62));
105110
105823
  /**
105111
105824
  * The update installed a build that never reported itself listening.
105112
105825
  *
@@ -105232,7 +105945,7 @@ const runServiceCommand = Effect.fn("cli.service.run")(function* (flags, run, pr
105232
105945
  const baseDirNotice = yield* describeNonDefaultBaseDir(config.baseDir);
105233
105946
  if (baseDirNotice !== null) yield* Console.error(baseDirNotice);
105234
105947
  if (prepare !== void 0) yield* prepare(config);
105235
- return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$61)));
105948
+ return yield* run.pipe(Effect.tapError((error) => isBootServiceCommandError(error) ? BootService.pipe(Effect.flatMap((service) => Console.error(`Details: ${service.logPath}`))) : Effect.void), Effect.provide(Layer.mergeAll(bootServiceLayer(config), layer$62)));
105236
105949
  });
105237
105950
  /**
105238
105951
  * Options the installed unit carries, rather than ones this command consumes.
@@ -105399,7 +106112,7 @@ const serviceCommand = Command.make("service").pipe(Command.withDescription("Man
105399
106112
  ]));
105400
106113
  //#endregion
105401
106114
  //#region src/bin.ts
105402
- const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$79, FetchHttpClient.layer);
106115
+ const CliRuntimeLayer = Layer.mergeAll(NodeServices.layer, layer$80, FetchHttpClient.layer);
105403
106116
  /**
105404
106117
  * Prints an update reminder before dispatching, at most once a day.
105405
106118
  *