@treeseed/sdk 0.6.39 → 0.6.41

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.
Files changed (44) hide show
  1. package/dist/capacity.d.ts +53 -0
  2. package/dist/capacity.js +100 -0
  3. package/dist/control-plane-client.d.ts +41 -1
  4. package/dist/control-plane-client.js +154 -0
  5. package/dist/control-plane.d.ts +6 -1
  6. package/dist/control-plane.js +39 -2
  7. package/dist/d1-store.d.ts +63 -1
  8. package/dist/d1-store.js +190 -1
  9. package/dist/index.d.ts +3 -1
  10. package/dist/index.js +12 -0
  11. package/dist/operations/services/config-runtime.js +2 -2
  12. package/dist/operations/services/deploy.js +3 -2
  13. package/dist/operations/services/knowledge-coop-launch.js +5 -28
  14. package/dist/operations/services/package-reference-policy.d.ts +68 -0
  15. package/dist/operations/services/package-reference-policy.js +135 -0
  16. package/dist/operations/services/project-platform.d.ts +14 -0
  17. package/dist/operations/services/project-platform.js +3 -2
  18. package/dist/operations/services/railway-api.d.ts +33 -0
  19. package/dist/operations/services/railway-api.js +273 -0
  20. package/dist/operations/services/railway-deploy.d.ts +22 -0
  21. package/dist/operations/services/railway-deploy.js +216 -18
  22. package/dist/operations/services/release-candidate.d.ts +2 -0
  23. package/dist/operations/services/release-candidate.js +28 -0
  24. package/dist/operations/services/runtime-tools.js +1 -1
  25. package/dist/operations-registry.js +1 -0
  26. package/dist/reconcile/bootstrap-systems.js +1 -1
  27. package/dist/reconcile/builtin-adapters.js +5 -9
  28. package/dist/reconcile/contracts.d.ts +1 -1
  29. package/dist/reconcile/desired-state.js +9 -17
  30. package/dist/reconcile/state.js +4 -4
  31. package/dist/reconcile/units.js +4 -8
  32. package/dist/sdk-types.d.ts +566 -3
  33. package/dist/sdk.d.ts +12 -1
  34. package/dist/sdk.js +44 -0
  35. package/dist/stores/operational-store.d.ts +12 -1
  36. package/dist/stores/operational-store.js +283 -5
  37. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +5 -24
  38. package/dist/types/agents.d.ts +27 -0
  39. package/dist/workflow/operations.d.ts +94 -2
  40. package/dist/workflow/operations.js +90 -32
  41. package/dist/workflow-state.js +3 -5
  42. package/dist/workflow.d.ts +8 -1
  43. package/dist/workflow.js +6 -0
  44. package/package.json +5 -1
package/dist/d1-store.js CHANGED
@@ -54,6 +54,11 @@ class MemoryAgentDatabase {
54
54
  graphRuns = /* @__PURE__ */ new Map();
55
55
  reports = /* @__PURE__ */ new Map();
56
56
  workPolicies = /* @__PURE__ */ new Map();
57
+ workdayRequests = /* @__PURE__ */ new Map();
58
+ workdayManagerLeases = /* @__PURE__ */ new Map();
59
+ workerRunners = /* @__PURE__ */ new Map();
60
+ repositoryClaims = /* @__PURE__ */ new Map();
61
+ runnerScaleDecisions = /* @__PURE__ */ new Map();
57
62
  priorityOverrides = /* @__PURE__ */ new Map();
58
63
  prioritySnapshots = /* @__PURE__ */ new Map();
59
64
  taskCreditLedger = /* @__PURE__ */ new Map();
@@ -761,11 +766,19 @@ class MemoryAgentDatabase {
761
766
  return this.workPolicies.get(`${projectId}:${environment}`) ?? null;
762
767
  }
763
768
  async upsertWorkPolicy(request) {
769
+ const dailyCreditBudget = Number(request.dailyCreditBudget ?? request.dailyTaskCreditBudget ?? 0);
764
770
  const policy = {
765
771
  projectId: request.projectId,
766
772
  environment: request.environment,
767
773
  schedule: request.schedule,
768
- dailyTaskCreditBudget: request.dailyTaskCreditBudget,
774
+ enabled: request.enabled ?? true,
775
+ startCron: request.startCron ?? "0 9 * * 1-5",
776
+ durationMinutes: Number(request.durationMinutes ?? 480),
777
+ maxRunners: Number(request.maxRunners ?? request.autoscale.maxWorkers ?? 1),
778
+ maxWorkersPerRunner: Number(request.maxWorkersPerRunner ?? 4),
779
+ dailyCreditBudget,
780
+ closeoutGraceMinutes: Number(request.closeoutGraceMinutes ?? 15),
781
+ dailyTaskCreditBudget: dailyCreditBudget,
769
782
  maxQueuedTasks: request.maxQueuedTasks,
770
783
  maxQueuedCredits: request.maxQueuedCredits,
771
784
  autoscale: request.autoscale,
@@ -775,6 +788,149 @@ class MemoryAgentDatabase {
775
788
  this.workPolicies.set(`${request.projectId}:${request.environment}`, policy);
776
789
  return policy;
777
790
  }
791
+ async createWorkdayRequest(request) {
792
+ const timestamp = nowIso();
793
+ const record = {
794
+ id: request.id ?? crypto.randomUUID(),
795
+ projectId: request.projectId,
796
+ environment: request.environment,
797
+ type: request.type,
798
+ state: request.state ?? "pending",
799
+ workDayId: request.workDayId ?? null,
800
+ requestedBy: request.requestedBy ?? null,
801
+ reason: request.reason ?? null,
802
+ payload: request.payload ?? {},
803
+ metadata: request.metadata ?? {},
804
+ createdAt: timestamp,
805
+ updatedAt: timestamp
806
+ };
807
+ this.workdayRequests.set(record.id, record);
808
+ return record;
809
+ }
810
+ async listWorkdayRequests(projectId, environment, state) {
811
+ return [...this.workdayRequests.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).filter((entry) => !state || entry.state === state).sort((left, right) => left.createdAt.localeCompare(right.createdAt));
812
+ }
813
+ async claimWorkdayManagerLease(request) {
814
+ const timestamp = request.now ?? nowIso();
815
+ const nowMs = Date.parse(timestamp);
816
+ const staleAfterMs = (request.staleAfterSeconds ?? request.ttlSeconds) * 1e3;
817
+ const existing = [...this.workdayManagerLeases.values()].find((entry) => entry.projectId === request.projectId && entry.environment === request.environment && entry.state === "active");
818
+ if (existing && existing.managerId !== request.managerId) {
819
+ const heartbeatMs = Date.parse(existing.heartbeatAt);
820
+ if (Number.isFinite(heartbeatMs) && Number.isFinite(nowMs) && nowMs - heartbeatMs <= staleAfterMs) {
821
+ return null;
822
+ }
823
+ }
824
+ const id = existing?.id ?? request.id ?? crypto.randomUUID();
825
+ const record = {
826
+ id,
827
+ projectId: request.projectId,
828
+ environment: request.environment,
829
+ workDayId: request.workDayId ?? existing?.workDayId ?? null,
830
+ managerId: request.managerId,
831
+ state: "active",
832
+ heartbeatAt: timestamp,
833
+ expiresAt: new Date(Date.parse(timestamp) + request.ttlSeconds * 1e3).toISOString(),
834
+ metadata: request.metadata ?? existing?.metadata ?? {},
835
+ createdAt: existing?.createdAt ?? timestamp,
836
+ updatedAt: timestamp
837
+ };
838
+ this.workdayManagerLeases.set(id, record);
839
+ return record;
840
+ }
841
+ async releaseWorkdayManagerLease(request) {
842
+ const existing = this.workdayManagerLeases.get(request.id);
843
+ if (!existing || existing.managerId !== request.managerId) return null;
844
+ const next = { ...existing, state: "released", updatedAt: nowIso() };
845
+ this.workdayManagerLeases.set(next.id, next);
846
+ return next;
847
+ }
848
+ async recordWorkerRunner(request) {
849
+ const timestamp = nowIso();
850
+ const id = request.id ?? `${request.projectId}:${request.environment}:${request.runnerId}`;
851
+ const activeLocalWorkers = Number(request.activeLocalWorkers ?? 0);
852
+ const maxLocalWorkers = Number(request.maxLocalWorkers ?? 4);
853
+ const record = {
854
+ id,
855
+ projectId: request.projectId,
856
+ environment: request.environment,
857
+ runnerId: request.runnerId,
858
+ runnerServiceName: request.runnerServiceName,
859
+ volumeIdentity: request.volumeIdentity,
860
+ state: request.state ?? "active",
861
+ maxLocalWorkers,
862
+ activeLocalWorkers,
863
+ availableCapacity: Math.max(0, maxLocalWorkers - activeLocalWorkers),
864
+ lastHeartbeatAt: timestamp,
865
+ claimedRepositoryIds: request.claimedRepositoryIds ?? [],
866
+ metadata: request.metadata ?? {},
867
+ createdAt: this.workerRunners.get(id)?.createdAt ?? timestamp,
868
+ updatedAt: timestamp
869
+ };
870
+ this.workerRunners.set(id, record);
871
+ return record;
872
+ }
873
+ async listWorkerRunners(projectId, environment) {
874
+ return [...this.workerRunners.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).sort((left, right) => left.runnerId.localeCompare(right.runnerId));
875
+ }
876
+ async recordRepositoryClaim(request) {
877
+ const timestamp = nowIso();
878
+ const id = request.id ?? `${request.projectId}:${request.repositoryId}:${request.runnerId}`;
879
+ const record = {
880
+ id,
881
+ projectId: request.projectId,
882
+ repositoryId: request.repositoryId,
883
+ runnerId: request.runnerId,
884
+ runnerServiceName: request.runnerServiceName,
885
+ volumeIdentity: request.volumeIdentity,
886
+ lastSeenCommit: request.lastSeenCommit ?? null,
887
+ lastTaskAt: request.lastTaskAt ?? timestamp,
888
+ claimState: request.claimState ?? "active",
889
+ metadata: request.metadata ?? {},
890
+ createdAt: this.repositoryClaims.get(id)?.createdAt ?? timestamp,
891
+ updatedAt: timestamp
892
+ };
893
+ this.repositoryClaims.set(id, record);
894
+ return record;
895
+ }
896
+ async listRepositoryClaims(projectId, repositoryId) {
897
+ return [...this.repositoryClaims.values()].filter((entry) => entry.projectId === projectId).filter((entry) => !repositoryId || entry.repositoryId === repositoryId).sort((left, right) => right.updatedAt.localeCompare(left.updatedAt));
898
+ }
899
+ async recordRunnerScaleDecision(request) {
900
+ const record = {
901
+ id: request.id ?? crypto.randomUUID(),
902
+ projectId: request.projectId,
903
+ environment: request.environment,
904
+ workDayId: request.workDayId ?? null,
905
+ runnerId: request.runnerId ?? null,
906
+ runnerServiceName: request.runnerServiceName ?? null,
907
+ action: request.action,
908
+ reason: request.reason,
909
+ metadata: request.metadata ?? {},
910
+ createdAt: nowIso()
911
+ };
912
+ this.runnerScaleDecisions.set(record.id, record);
913
+ return record;
914
+ }
915
+ async listRunnerScaleDecisions(projectId, environment, workDayId) {
916
+ return [...this.runnerScaleDecisions.values()].filter((entry) => entry.projectId === projectId && entry.environment === environment).filter((entry) => !workDayId || entry.workDayId === workDayId).sort((left, right) => right.createdAt.localeCompare(left.createdAt));
917
+ }
918
+ async updateWorkDayGraph(request) {
919
+ const existing = this.workDays.get(request.id);
920
+ if (!existing) return null;
921
+ const summary = {
922
+ ...existing.summaryJson ? JSON.parse(existing.summaryJson) : {},
923
+ ...request.summaryPatch ?? {}
924
+ };
925
+ const next = {
926
+ ...existing,
927
+ graphVersion: request.graphVersion,
928
+ summaryJson: JSON.stringify(summary),
929
+ updatedAt: nowIso()
930
+ };
931
+ this.workDays.set(next.id, next);
932
+ return next;
933
+ }
778
934
  async listPriorityOverrides(projectId) {
779
935
  return [...this.priorityOverrides.values()].filter((entry) => entry.projectId === projectId);
780
936
  }
@@ -1244,6 +1400,39 @@ class CloudflareD1AgentDatabase {
1244
1400
  upsertWorkPolicy(request) {
1245
1401
  return this.operational.upsertWorkPolicy(request);
1246
1402
  }
1403
+ createWorkdayRequest(request) {
1404
+ return this.operational.createWorkdayRequest(request);
1405
+ }
1406
+ listWorkdayRequests(projectId, environment, state) {
1407
+ return this.operational.listWorkdayRequests(projectId, environment, state);
1408
+ }
1409
+ claimWorkdayManagerLease(request) {
1410
+ return this.operational.claimWorkdayManagerLease(request);
1411
+ }
1412
+ releaseWorkdayManagerLease(request) {
1413
+ return this.operational.releaseWorkdayManagerLease(request);
1414
+ }
1415
+ recordWorkerRunner(request) {
1416
+ return this.operational.recordWorkerRunner(request);
1417
+ }
1418
+ listWorkerRunners(projectId, environment) {
1419
+ return this.operational.listWorkerRunners(projectId, environment);
1420
+ }
1421
+ recordRepositoryClaim(request) {
1422
+ return this.operational.recordRepositoryClaim(request);
1423
+ }
1424
+ listRepositoryClaims(projectId, repositoryId) {
1425
+ return this.operational.listRepositoryClaims(projectId, repositoryId);
1426
+ }
1427
+ recordRunnerScaleDecision(request) {
1428
+ return this.operational.recordRunnerScaleDecision(request);
1429
+ }
1430
+ listRunnerScaleDecisions(projectId, environment, workDayId) {
1431
+ return this.operational.listRunnerScaleDecisions(projectId, environment, workDayId);
1432
+ }
1433
+ updateWorkDayGraph(request) {
1434
+ return this.operational.updateWorkDayGraph(request);
1435
+ }
1247
1436
  listPriorityOverrides(projectId) {
1248
1437
  return this.operational.listPriorityOverrides(projectId);
1249
1438
  }
package/dist/index.d.ts CHANGED
@@ -3,6 +3,7 @@ export { ContentGraphRuntime } from './graph.ts';
3
3
  export { projectConnectionModeFromHosting } from './sdk-types.ts';
4
4
  export { createControlPlaneReporter } from './control-plane.ts';
5
5
  export { ControlPlaneClient } from './control-plane-client.ts';
6
+ export { reservationHasCapacity, reserveCreditsForEstimate, scoreCapacityLane, selectBestCapacityLane, summarizeCapacityPlan, } from './capacity.ts';
6
7
  export { executeKnowledgeCoopManagedLaunch, validateKnowledgeCoopManagedLaunchPrerequisites, } from './operations/services/knowledge-coop-launch.ts';
7
8
  export { ensureRailwayEnvironment, ensureRailwayProject, ensureRailwayService, getRailwayAuthProfile, listRailwayEnvironments, listRailwayProjects, listRailwayServices, listRailwayVariables, railwayGraphqlRequest, resolveRailwayApiToken, resolveRailwayApiUrl, resolveRailwayWorkspace, resolveRailwayWorkspaceContext, upsertRailwayVariables, } from './operations/services/railway-api.ts';
8
9
  export { buildKnowledgeCoopKnowledgePackPackage, buildKnowledgeCoopTemplatePackage, importKnowledgeCoopKnowledgePack, } from './operations/services/knowledge-coop-packaging.ts';
@@ -30,10 +31,11 @@ export { TreeseedWorkflowSdk } from './workflow.ts';
30
31
  export * from './db/index.ts';
31
32
  export { collectTreeseedReconcileStatus, createTreeseedReconcileRegistry, deriveTreeseedDesiredUnits, destroyTreeseedTargetUnits, observeTreeseedUnits, planTreeseedReconciliation, reconcileTreeseedTarget, } from './reconcile/index.ts';
32
33
  export { getTreeseedVerifyDriverStatus, runTreeseedVerifyDriver } from './verification.ts';
33
- export type { KnowledgeCoopLaunchPreflightReport, KnowledgeCoopLaunchFailurePhase, KnowledgeCoopManagedLaunchInput, KnowledgeCoopManagedLaunchResult, AgentMessageKind, AgentMessageRecord, AgentStatusRecord, DirectBoardItemSummary, InboxItem, KnowledgeCoopJobStatus, LaunchProjectRequest, LaunchProjectResult, LinkedProjectRecordRef, ProjectConnectionStatus, ProjectOverviewSummary, ReleaseDetail, ReleaseState, ReleaseSummary, SharePackageState, SharePackageStatus, TeamCapability, TeamHomeSummary, TeamMemberSummary, WorkstreamDetail, WorkstreamEvent, WorkstreamState, WorkstreamSummary, SdkContentEntry, SdkDispatchCapability, SdkDispatchConfig, SdkDispatchCredentialSource, SdkDispatchExecutionClass, SdkDispatchNamespace, SdkDispatchPolicy, SdkDispatchRequest, SdkDispatchResult, SdkDispatchTarget, SdkCursorEntity, SdkFilterCondition, SdkFollowRequest, SdkGraphEdge, SdkGraphEdgeType, SdkGraphDslRelation, SdkGraphDslParseResult, SdkGraphModelConfig, SdkGraphNode, SdkGraphNodeType, SdkGraphPathExplanation, SdkGraphQueryStage, SdkGraphQueryView, SdkGraphQueryOptions, SdkGraphQueryRequest, SdkGraphQueryResult, SdkGraphRankingBuildInput, SdkGraphRankingDiagnostics, SdkGraphRankingIndex, SdkGraphRankingNodeResult, SdkGraphRankingProvider, SdkGraphRankingQueryRequest, SdkGraphRankingQueryResult, SdkGraphRankingSearchRequest, SdkGraphRefreshPayload, SdkGraphRefreshRequest, SdkGraphSearchOptions, SdkGraphSearchResult, SdkGraphSeed, SdkGraphSeedResolution, SdkGraphTraversalResult, SdkGraphWhereFilter, SdkContextPack, SdkContextPackRequest, SdkGetRequest, SdkJsonEnvelope, SdkLeaseEntity, SdkManagerContextPayload, SdkMessageEntity, SdkModelFieldBinding, SdkModelDefinition, SdkModelRegistry, SdkModelName, SdkMutationRequest, SdkOperation, SdkPickRequest, SdkPickResult, SdkQueueMessageEnvelope, SdkRunEntity, SdkSearchRequest, SdkTaskEntity, SdkTaskEventEntity, SdkTaskOutputEntity, SdkWorkDayEntity, SdkGraphRunEntity, SdkReportEntity, SdkSubscriptionEntity, SdkTemplateCatalogEntry, SdkTemplateCatalogPublisher, SdkTemplateCatalogResponse, SdkTemplateCatalogSource, SdkUpdateRequest, ProjectCapabilityGrant, ProjectConnection, ProjectConnectionMode, ProjectDeployment, ProjectDeploymentKind, ProjectDeploymentStatus, ProjectEnvironment, ProjectExecutionOwner, ProjectHosting, ProjectInfrastructureResource, ProjectInfrastructureResourceKind, ProjectInfrastructureResourceProvider, ProjectRunnerRegistrationState, RemoteJob, RemoteJobEvent, RemoteJobStatus, AgentPool, AgentPoolAutoscalePolicy, AgentPoolRegistration, AgentPoolScaleDecision, AgentPoolStatus, CatalogArtifactVersion, CatalogItem, CatalogItemFilters, CatalogItemOfferMode, ProjectEnvironmentName, ProjectWorkdaySummary, TreeseedHostingKind, TreeseedHostingRegistration, PriorityOverride, WorkdayWindow, WorkdaySchedule, TaskCreditWeight, TaskCreditBudget, WorkdayPolicy, PrioritySnapshotItem, PrioritySnapshot, TaskCreditLedgerEntry, ScaleDecision, TeamStorageLocator, TeamWebHost, TeamWebHostOwnership, TeamWebHostProvider, EncryptedWebHostPayload, UpsertAgentPoolRequest, UpsertCatalogArtifactVersionRequest, UpsertCatalogItemRequest, UpsertProjectEnvironmentRequest, UpsertProjectHostingRequest, UpsertProjectInfrastructureResourceRequest, UpsertTeamStorageLocatorRequest, UpsertTeamWebHostRequest, CreateProjectDeploymentRequest, RecordAgentPoolRegistrationRequest, WorkerPoolScaleResult, WorkerPoolScaler, } from './sdk-types.ts';
34
+ export type { KnowledgeCoopLaunchPreflightReport, KnowledgeCoopLaunchFailurePhase, KnowledgeCoopManagedLaunchInput, KnowledgeCoopManagedLaunchResult, AgentMessageKind, AgentMessageRecord, AgentStatusRecord, DirectBoardItemSummary, InboxItem, KnowledgeCoopJobStatus, LaunchProjectRequest, LaunchProjectResult, LinkedProjectRecordRef, ProjectConnectionStatus, ProjectOverviewSummary, ReleaseDetail, ReleaseState, ReleaseSummary, SharePackageState, SharePackageStatus, TeamCapability, TeamHomeSummary, TeamMemberSummary, WorkstreamDetail, WorkstreamEvent, WorkstreamState, WorkstreamSummary, SdkContentEntry, SdkDispatchCapability, SdkDispatchConfig, SdkDispatchCredentialSource, SdkDispatchExecutionClass, SdkDispatchNamespace, SdkDispatchPolicy, SdkDispatchRequest, SdkDispatchResult, SdkDispatchTarget, SdkCursorEntity, SdkFilterCondition, SdkFollowRequest, SdkGraphEdge, SdkGraphEdgeType, SdkGraphDslRelation, SdkGraphDslParseResult, SdkGraphModelConfig, SdkGraphNode, SdkGraphNodeType, SdkGraphPathExplanation, SdkGraphQueryStage, SdkGraphQueryView, SdkGraphQueryOptions, SdkGraphQueryRequest, SdkGraphQueryResult, SdkGraphRankingBuildInput, SdkGraphRankingDiagnostics, SdkGraphRankingIndex, SdkGraphRankingNodeResult, SdkGraphRankingProvider, SdkGraphRankingQueryRequest, SdkGraphRankingQueryResult, SdkGraphRankingSearchRequest, SdkGraphRefreshPayload, SdkGraphRefreshRequest, SdkGraphSearchOptions, SdkGraphSearchResult, SdkGraphSeed, SdkGraphSeedResolution, SdkGraphTraversalResult, SdkGraphWhereFilter, SdkContextPack, SdkContextPackRequest, SdkGetRequest, SdkJsonEnvelope, SdkLeaseEntity, SdkManagerContextPayload, SdkMessageEntity, SdkModelFieldBinding, SdkModelDefinition, SdkModelRegistry, SdkModelName, SdkMutationRequest, SdkOperation, SdkPickRequest, SdkPickResult, SdkQueueMessageEnvelope, SdkRunEntity, SdkSearchRequest, SdkTaskEntity, SdkTaskEventEntity, SdkTaskOutputEntity, SdkWorkDayEntity, SdkGraphRunEntity, SdkReportEntity, SdkSubscriptionEntity, SdkTemplateCatalogEntry, SdkTemplateCatalogPublisher, SdkTemplateCatalogResponse, SdkTemplateCatalogSource, SdkUpdateRequest, ProjectCapabilityGrant, ProjectConnection, ProjectConnectionMode, ProjectDeployment, ProjectDeploymentKind, ProjectDeploymentStatus, ProjectEnvironment, ProjectExecutionOwner, ProjectHosting, ProjectInfrastructureResource, ProjectInfrastructureResourceKind, ProjectInfrastructureResourceProvider, ProjectRunnerRegistrationState, RemoteJob, RemoteJobEvent, RemoteJobStatus, AgentPool, AgentPoolAutoscalePolicy, AgentPoolRegistration, AgentPoolScaleDecision, AgentPoolStatus, CatalogArtifactVersion, CatalogItem, CatalogItemFilters, CatalogItemOfferMode, ProjectEnvironmentName, ProjectWorkdaySummary, TreeseedHostingKind, TreeseedHostingRegistration, PriorityOverride, WorkdayWindow, WorkdaySchedule, WorkdayRequest, WorkdayManagerLease, WorkerRunner, WorkerRunnerState, RepositoryClaim, TaskCreditWeight, TaskCreditBudget, WorkdayPolicy, PrioritySnapshotItem, PrioritySnapshot, TaskCreditLedgerEntry, ApprovalRequest, CapacityBusinessModel, CapacityGrant, CapacityGrantScope, CapacityLedgerEntry, CapacityLaneUnit, CapacityPlan, CapacityProvider, CapacityProviderHost, CapacityProviderKind, CapacityProviderLane, CapacityReservation, CapacityRoutingDecision, CapacityTaskExecutionEnvelope, CreateApprovalRequestRequest, CreateCapacityReservationRequest, CreateCapacityRoutingDecisionRequest, CreateTaskEstimateRequest, CreateTaskUsageActualRequest, RecordCapacityUsageRequest, TaskEstimate, TaskEstimateProfile, TaskUsageActual, UpsertCapacityGrantRequest, UpsertCapacityProviderHostRequest, UpsertCapacityProviderLaneRequest, UpsertCapacityProviderRequest, ScaleDecision, RunnerScaleDecision, TeamStorageLocator, TeamWebHost, TeamWebHostOwnership, TeamWebHostProvider, EncryptedWebHostPayload, UpsertAgentPoolRequest, UpsertCatalogArtifactVersionRequest, UpsertCatalogItemRequest, UpsertProjectEnvironmentRequest, UpsertProjectHostingRequest, UpsertProjectInfrastructureResourceRequest, UpsertTeamStorageLocatorRequest, UpsertTeamWebHostRequest, CreateProjectDeploymentRequest, RecordAgentPoolRegistrationRequest, SdkCreateWorkdayRequest, SdkClaimWorkdayManagerLeaseRequest, SdkReleaseWorkdayManagerLeaseRequest, SdkRecordWorkerRunnerRequest, SdkRecordRepositoryClaimRequest, SdkRecordRunnerScaleDecisionRequest, SdkUpdateWorkDayGraphRequest, WorkerPoolScaleResult, WorkerPoolScaler, } from './sdk-types.ts';
34
35
  export type * from './knowledge-coop.ts';
35
36
  export type { ControlPlaneAgentPoolHeartbeat, ControlPlaneDeploymentReport, ControlPlaneEnvironmentReport, ControlPlaneReporter, ControlPlaneReporterKind, ControlPlaneResourceReport, ControlPlaneScaleDecisionReport, ControlPlaneWorkdaySummaryReport, } from './control-plane.ts';
36
37
  export type { ControlPlaneClientOptions } from './control-plane-client.ts';
38
+ export type { CapacityEstimateInput, CapacityLaneCandidate, CapacityLaneScore, } from './capacity.ts';
37
39
  export type { TreeseedFieldAliasBinding, TreeseedFieldAliasRegistry, } from './field-aliases.ts';
38
40
  export type * from './operations-types.ts';
39
41
  export type * from './workflow.ts';
package/dist/index.js CHANGED
@@ -3,6 +3,13 @@ import { ContentGraphRuntime } from "./graph.js";
3
3
  import { projectConnectionModeFromHosting } from "./sdk-types.js";
4
4
  import { createControlPlaneReporter } from "./control-plane.js";
5
5
  import { ControlPlaneClient } from "./control-plane-client.js";
6
+ import {
7
+ reservationHasCapacity,
8
+ reserveCreditsForEstimate,
9
+ scoreCapacityLane,
10
+ selectBestCapacityLane,
11
+ summarizeCapacityPlan
12
+ } from "./capacity.js";
6
13
  import {
7
14
  executeKnowledgeCoopManagedLaunch,
8
15
  validateKnowledgeCoopManagedLaunchPrerequisites
@@ -290,6 +297,8 @@ export {
290
297
  readPublishedOverlayManifest,
291
298
  reconcileTreeseedTarget,
292
299
  removeMarketProfile,
300
+ reservationHasCapacity,
301
+ reserveCreditsForEstimate,
293
302
  resolveAliasedField,
294
303
  resolveCatalogMarketProfiles,
295
304
  resolveCloudflareR2Bucket,
@@ -314,9 +323,12 @@ export {
314
323
  resolveTreeseedToolCommand,
315
324
  runTreeseedCopilotTask,
316
325
  runTreeseedVerifyDriver,
326
+ scoreCapacityLane,
327
+ selectBestCapacityLane,
317
328
  setActiveMarketProfile,
318
329
  setMarketSession,
319
330
  signEditorialPreviewToken,
331
+ summarizeCapacityPlan,
320
332
  tenantFeatureEnabled,
321
333
  tenantModelRendered,
322
334
  upsertRailwayVariables,
@@ -2088,14 +2088,14 @@ function syncTreeseedRailwayEnvironment({ tenantRoot, scope = "prod", dryRun = f
2088
2088
  const registry = collectTreeseedEnvironmentContext(tenantRoot);
2089
2089
  const railwaySecretNames = registry.entries.filter((entry) => entry.scopes.includes(scope) && entry.targets.includes("railway-secret")).map((entry) => entry.id).filter((key) => typeof values[key] === "string" && values[key].length > 0);
2090
2090
  const railwayVariableNames = registry.entries.filter((entry) => entry.scopes.includes(scope) && entry.targets.includes("railway-var")).map((entry) => entry.id).filter((key) => typeof values[key] === "string" && values[key].length > 0);
2091
- const services = ["api", "manager", "worker", "workdayStart", "workdayReport"].map((serviceKey) => {
2091
+ const services = ["api", "workdayManager", "workerRunner"].map((serviceKey) => {
2092
2092
  const service = deployConfig.services?.[serviceKey];
2093
2093
  if (!service || service.enabled === false || (service.provider ?? "railway") !== "railway") {
2094
2094
  return null;
2095
2095
  }
2096
2096
  const environment = service.environments?.[scope];
2097
2097
  const fallbackServiceName = serviceKey === "api" ? config.settings.services.railway.apiServiceName : "";
2098
- const defaultRootDir = ["api", "manager", "worker", "workdayStart", "workdayReport"].includes(serviceKey) ? "." : "packages/core";
2098
+ const defaultRootDir = ["api", "workdayManager", "workerRunner"].includes(serviceKey) ? "." : "packages/core";
2099
2099
  return {
2100
2100
  service: serviceKey,
2101
2101
  projectName: service.railway?.projectName ?? config.settings.services.railway.projectName,
@@ -13,7 +13,7 @@ const GENERATED_ROOT = ".treeseed/generated";
13
13
  const STATE_ROOT = ".treeseed/state";
14
14
  const WORKTREE_METADATA_RELATIVE_PATH = ".treeseed/worktree.json";
15
15
  const PERSISTENT_SCOPES = /* @__PURE__ */ new Set(["local", "staging", "prod"]);
16
- const MANAGED_SERVICE_KEYS = ["api", "manager", "worker", "workdayStart", "workdayReport"];
16
+ const MANAGED_SERVICE_KEYS = ["api", "workdayManager", "workerRunner"];
17
17
  const TRESEED_ENVELOPE_SCHEMA_GENERATION = "runtime-envelopes-v1";
18
18
  const TRESEED_MIGRATION_WAVE_ID = "0005_runtime_envelopes";
19
19
  const TRESEED_SUPPORTED_PAYLOAD_RANGE = { min: 1, max: 1 };
@@ -154,7 +154,8 @@ function resolveConfiguredSurfaceBaseUrl(deployConfig, target, surface) {
154
154
  return null;
155
155
  }
156
156
  function sharedDeploymentName(identity, role = "") {
157
- return role ? `${identity.deploymentKey}-${sanitizeSegment(role)}` : identity.deploymentKey;
157
+ const roleSegment = role === "workdayManager" ? "workday-manager" : role === "workerRunner" ? "worker-runner-01" : role;
158
+ return role ? `${identity.deploymentKey}-${sanitizeSegment(roleSegment)}` : identity.deploymentKey;
158
159
  }
159
160
  function environmentScopedIdentityName(identity, role, target) {
160
161
  const environmentSegment = target.kind === "persistent" ? target.scope : sanitizeSegment(target.branchName);
@@ -324,47 +324,24 @@ function applyManagedProjectDefaults(projectRoot, input) {
324
324
  }
325
325
  }
326
326
  },
327
- manager: {
327
+ workdayManager: {
328
328
  enabled: managedRuntime,
329
329
  provider: managedRuntime ? "railway" : "none",
330
330
  railway: {
331
- serviceName: `${slug}-manager`,
331
+ serviceName: `${slug}-workday-manager`,
332
332
  rootDir: ".",
333
333
  buildCommand: "npm run build",
334
- startCommand: "node ./node_modules/@treeseed/core/dist/services/manager.js",
335
- schedule: "*/5 * * * *"
336
- }
337
- },
338
- worker: {
339
- enabled: managedRuntime,
340
- provider: managedRuntime ? "railway" : "none",
341
- railway: {
342
- serviceName: `${slug}-worker`,
343
- rootDir: ".",
344
- buildCommand: "npm run build",
345
- startCommand: "node ./node_modules/@treeseed/core/dist/services/worker.js"
346
- }
347
- },
348
- workdayStart: {
349
- enabled: managedRuntime,
350
- provider: managedRuntime ? "railway" : "none",
351
- railway: {
352
- serviceName: `${slug}-workday-start`,
353
- rootDir: ".",
354
- buildCommand: "npm run build",
355
- startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-start.js",
334
+ startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-manager.js",
356
335
  schedule: "0 9 * * 1-5"
357
336
  }
358
337
  },
359
- workdayReport: {
338
+ workerRunner: {
360
339
  enabled: managedRuntime,
361
340
  provider: managedRuntime ? "railway" : "none",
362
341
  railway: {
363
- serviceName: `${slug}-workday-report`,
364
342
  rootDir: ".",
365
343
  buildCommand: "npm run build",
366
- startCommand: "node ./node_modules/@treeseed/core/dist/services/workday-report.js",
367
- schedule: "5 17 * * 1-5"
344
+ startCommand: "node ./node_modules/@treeseed/core/dist/services/worker.js"
368
345
  }
369
346
  },
370
347
  ...config.services ?? {}
@@ -1,6 +1,7 @@
1
1
  export type DevDependencyReferenceMode = 'git-tag' | 'registry-prerelease';
2
2
  export type DevTagCleanupMode = 'safe-after-release' | 'off';
3
3
  export type GitDependencyProtocol = 'preserve-origin' | 'https' | 'ssh';
4
+ export type DevTagBranchScope = 'staging' | 'preview' | 'all';
4
5
  export type PackageDependencyReference = {
5
6
  packageName: string;
6
7
  version: string;
@@ -18,6 +19,22 @@ export type RewrittenDevReference = {
18
19
  to: string;
19
20
  tagName: string | null;
20
21
  };
22
+ export type TreeseedDevTagInfo = {
23
+ tagName: string;
24
+ stableVersion: string;
25
+ branchSlug: string;
26
+ timestamp: string;
27
+ metadata: Record<string, string>;
28
+ branch: string | null;
29
+ packageName: string | null;
30
+ version: string | null;
31
+ };
32
+ export type StaleDevTagClassification = {
33
+ tagName: string;
34
+ action: 'delete' | 'skip';
35
+ reason: string;
36
+ info: TreeseedDevTagInfo | null;
37
+ };
21
38
  export declare function internalDependencyFields(packageJson: Record<string, unknown> | null): string[];
22
39
  export declare function isPrereleaseVersion(version: string): boolean;
23
40
  export declare function isStableVersion(version: string): boolean;
@@ -61,6 +78,15 @@ export declare function createDevTagMessage(input: {
61
78
  }): string;
62
79
  export declare function gitTagMessage(repoDir: string, tagName: string): string;
63
80
  export declare function tagHasTreeseedDevMetadata(repoDir: string, tagName: string): boolean;
81
+ export declare function parseTreeseedDevTag(tagName: string, message: string): TreeseedDevTagInfo | null;
82
+ export declare function classifyStaleTreeseedDevTag(input: {
83
+ tagName: string;
84
+ message: string;
85
+ currentVersion: string;
86
+ activeReferences?: string[];
87
+ branchScope?: DevTagBranchScope;
88
+ expectedPackageName?: string | null;
89
+ }): StaleDevTagClassification;
64
90
  export declare function cleanupDevTags(repoDir: string, tagNames: string[], activeReferences?: string[]): {
65
91
  cleaned: string[];
66
92
  skipped: {
@@ -68,3 +94,45 @@ export declare function cleanupDevTags(repoDir: string, tagNames: string[], acti
68
94
  reason: string;
69
95
  }[];
70
96
  };
97
+ export declare function collectTreeseedDevTagCleanupPlan(input: {
98
+ repoDir: string;
99
+ packageName: string;
100
+ currentVersion: string;
101
+ activeReferences?: string[];
102
+ branchScope?: DevTagBranchScope;
103
+ }): {
104
+ packageName: string;
105
+ currentVersion: string;
106
+ branchScope: DevTagBranchScope;
107
+ candidates: StaleDevTagClassification[];
108
+ skipped: StaleDevTagClassification[];
109
+ tags: StaleDevTagClassification[];
110
+ };
111
+ export declare function cleanupStaleTreeseedDevTags(input: {
112
+ repoDir: string;
113
+ packageName: string;
114
+ currentVersion: string;
115
+ activeReferences?: string[];
116
+ branchScope?: DevTagBranchScope;
117
+ dryRun?: boolean;
118
+ }): {
119
+ status: string;
120
+ packageName: string;
121
+ currentVersion: string;
122
+ branchScope: DevTagBranchScope;
123
+ candidates: {
124
+ tagName: string;
125
+ reason: string;
126
+ branch: string | null | undefined;
127
+ branchSlug: string | undefined;
128
+ version: string | null | undefined;
129
+ }[];
130
+ candidateCount: number;
131
+ cleaned: string[];
132
+ cleanedCount: number;
133
+ skipped: {
134
+ tagName: string;
135
+ reason: string;
136
+ }[];
137
+ skippedCount: number;
138
+ };
@@ -20,6 +20,19 @@ function isPrereleaseVersion(version) {
20
20
  function isStableVersion(version) {
21
21
  return /^\d+\.\d+\.\d+$/u.test(String(version).trim());
22
22
  }
23
+ function stableVersionBase(version) {
24
+ const match = String(version).trim().match(/^(\d+\.\d+\.\d+)(?:-|$)/u);
25
+ return match?.[1] ?? null;
26
+ }
27
+ function compareStableVersions(left, right) {
28
+ const leftParts = left.split(".").map((part) => Number(part));
29
+ const rightParts = right.split(".").map((part) => Number(part));
30
+ for (let index = 0; index < 3; index += 1) {
31
+ const difference = (leftParts[index] ?? 0) - (rightParts[index] ?? 0);
32
+ if (difference !== 0) return difference;
33
+ }
34
+ return 0;
35
+ }
23
36
  function isGitDependencySpec(spec) {
24
37
  return /^(?:git\+|github:|gitlab:|bitbucket:|ssh:\/\/|https:\/\/|file:)/u.test(String(spec).trim()) && String(spec).includes("#");
25
38
  }
@@ -279,9 +292,68 @@ function gitTagMessage(repoDir, tagName) {
279
292
  return "";
280
293
  }
281
294
  }
295
+ function gitRemoteTagMessage(repoDir, tagName) {
296
+ try {
297
+ run("git", ["fetch", "--no-tags", "origin", `refs/tags/${tagName}`], { cwd: repoDir, capture: true });
298
+ return run("git", ["cat-file", "-p", "FETCH_HEAD"], { cwd: repoDir, capture: true });
299
+ } catch {
300
+ return "";
301
+ }
302
+ }
303
+ function gitDevTagMessage(repoDir, tagName) {
304
+ const local = gitTagMessage(repoDir, tagName);
305
+ if (local.trim()) return local;
306
+ return gitRemoteTagMessage(repoDir, tagName);
307
+ }
282
308
  function tagHasTreeseedDevMetadata(repoDir, tagName) {
283
309
  return gitTagMessage(repoDir, tagName).includes("treeseed-dev-tag: true");
284
310
  }
311
+ function parseTreeseedDevTag(tagName, message) {
312
+ const match = String(tagName).match(/^(\d+\.\d+\.\d+)-dev\.([0-9A-Za-z.-]+)\.(\d{8}T\d{6}Z)$/u);
313
+ if (!match) return null;
314
+ const metadata = Object.fromEntries(
315
+ String(message).split(/\r?\n/u).map((line) => line.match(/^([^:]+):\s*(.*)$/u)).filter((lineMatch) => Boolean(lineMatch)).map((lineMatch) => [String(lineMatch[1]).trim(), String(lineMatch[2] ?? "").trim()])
316
+ );
317
+ if (metadata["treeseed-dev-tag"] !== "true") return null;
318
+ return {
319
+ tagName,
320
+ stableVersion: match[1],
321
+ branchSlug: match[2],
322
+ timestamp: match[3],
323
+ metadata,
324
+ branch: metadata.branch || null,
325
+ packageName: metadata.package || null,
326
+ version: metadata.version || null
327
+ };
328
+ }
329
+ function devTagScope(info) {
330
+ const branch = info.branch ?? info.branchSlug;
331
+ if (branch === "staging" || info.branchSlug === "staging") return "staging";
332
+ if (branch === "main" || branch === "prod" || branch === "production" || info.branchSlug === "main" || info.branchSlug === "prod" || info.branchSlug === "production") return "main";
333
+ return "preview";
334
+ }
335
+ function classifyStaleTreeseedDevTag(input) {
336
+ const tagName = String(input.tagName).trim();
337
+ if (!tagName.includes("-dev.")) return { tagName, action: "skip", reason: "not-dev-tag", info: null };
338
+ if (tagName.startsWith("deprecated/")) return { tagName, action: "skip", reason: "deprecated-tag", info: null };
339
+ const info = parseTreeseedDevTag(tagName, input.message);
340
+ if (!info) return { tagName, action: "skip", reason: input.message.includes("treeseed-dev-tag: true") ? "malformed-dev-tag" : "missing-treeseed-metadata", info: null };
341
+ if (input.expectedPackageName && info.packageName && info.packageName !== input.expectedPackageName) {
342
+ return { tagName, action: "skip", reason: "package-mismatch", info };
343
+ }
344
+ if ((input.activeReferences ?? []).includes(tagName)) return { tagName, action: "skip", reason: "still-referenced", info };
345
+ const scope = devTagScope(info);
346
+ if (scope === "main") return { tagName, action: "skip", reason: "main-or-production-tag", info };
347
+ const branchScope = input.branchScope ?? "all";
348
+ if (branchScope !== "all" && branchScope !== scope) return { tagName, action: "skip", reason: `scope-${scope}`, info };
349
+ const currentStableVersion = stableVersionBase(input.currentVersion);
350
+ if (!currentStableVersion) return { tagName, action: "skip", reason: "invalid-current-version", info };
351
+ const comparison = compareStableVersions(info.stableVersion, currentStableVersion);
352
+ if (comparison >= 0) {
353
+ return { tagName, action: "skip", reason: comparison === 0 ? "current-version" : "newer-version", info };
354
+ }
355
+ return { tagName, action: "delete", reason: "stale-before-current-version", info };
356
+ }
285
357
  function cleanupDevTags(repoDir, tagNames, activeReferences = []) {
286
358
  const active = new Set(activeReferences.filter(Boolean));
287
359
  const cleaned = [];
@@ -309,10 +381,72 @@ function cleanupDevTags(repoDir, tagNames, activeReferences = []) {
309
381
  }
310
382
  return { cleaned, skipped };
311
383
  }
384
+ function localDevTags(repoDir) {
385
+ return run("git", ["tag", "-l", "*-dev.*"], { cwd: repoDir, capture: true }).split(/\r?\n/u).map((line) => line.trim()).filter(Boolean);
386
+ }
387
+ function remoteDevTags(repoDir) {
388
+ try {
389
+ return run("git", ["ls-remote", "--tags", "origin", "*-dev.*"], { cwd: repoDir, capture: true }).split(/\r?\n/u).map((line) => line.trim()).filter(Boolean).filter((line) => !line.endsWith("^{}")).map((line) => line.split(/\s+/u)[1] ?? "").filter((ref) => ref.startsWith("refs/tags/")).map((ref) => ref.slice("refs/tags/".length));
390
+ } catch {
391
+ return [];
392
+ }
393
+ }
394
+ function collectTreeseedDevTagCleanupPlan(input) {
395
+ const tagNames = [.../* @__PURE__ */ new Set([...localDevTags(input.repoDir), ...remoteDevTags(input.repoDir)])].sort();
396
+ const classifications = tagNames.map((tagName) => classifyStaleTreeseedDevTag({
397
+ tagName,
398
+ message: gitDevTagMessage(input.repoDir, tagName),
399
+ currentVersion: input.currentVersion,
400
+ activeReferences: input.activeReferences ?? [],
401
+ branchScope: input.branchScope ?? "all",
402
+ expectedPackageName: input.packageName
403
+ }));
404
+ return {
405
+ packageName: input.packageName,
406
+ currentVersion: input.currentVersion,
407
+ branchScope: input.branchScope ?? "all",
408
+ candidates: classifications.filter((classification) => classification.action === "delete"),
409
+ skipped: classifications.filter((classification) => classification.action === "skip"),
410
+ tags: classifications
411
+ };
412
+ }
413
+ function cleanupStaleTreeseedDevTags(input) {
414
+ const plan = collectTreeseedDevTagCleanupPlan(input);
415
+ const cleaned = [];
416
+ const skipped = [...plan.skipped.map((entry) => ({ tagName: entry.tagName, reason: entry.reason }))];
417
+ for (const candidate of plan.candidates) {
418
+ if (input.dryRun) continue;
419
+ try {
420
+ run("git", ["tag", "-d", candidate.tagName], { cwd: input.repoDir });
421
+ } catch {
422
+ }
423
+ try {
424
+ run("git", ["push", "origin", `:refs/tags/${candidate.tagName}`], { cwd: input.repoDir });
425
+ cleaned.push(candidate.tagName);
426
+ } catch (error) {
427
+ skipped.push({ tagName: candidate.tagName, reason: error instanceof Error ? error.message : String(error) });
428
+ }
429
+ }
430
+ return {
431
+ status: input.dryRun ? "planned" : "completed",
432
+ packageName: input.packageName,
433
+ currentVersion: input.currentVersion,
434
+ branchScope: input.branchScope ?? "all",
435
+ candidates: plan.candidates.map((entry) => ({ tagName: entry.tagName, reason: entry.reason, branch: entry.info?.branch, branchSlug: entry.info?.branchSlug, version: entry.info?.version })),
436
+ candidateCount: plan.candidates.length,
437
+ cleaned,
438
+ cleanedCount: cleaned.length,
439
+ skipped,
440
+ skippedCount: skipped.length
441
+ };
442
+ }
312
443
  export {
313
444
  assertNoInternalDevReferences,
445
+ classifyStaleTreeseedDevTag,
314
446
  cleanupDevTags,
447
+ cleanupStaleTreeseedDevTags,
315
448
  collectInternalDevReferenceIssues,
449
+ collectTreeseedDevTagCleanupPlan,
316
450
  createDevTagMessage,
317
451
  createPackageDependencyReference,
318
452
  devTagFromDependencySpec,
@@ -323,6 +457,7 @@ export {
323
457
  isStableVersion,
324
458
  normalizeGitRemoteForDependency,
325
459
  normalizeGitRemoteForManifest,
460
+ parseTreeseedDevTag,
326
461
  rewriteInternalDependenciesToStableVersions,
327
462
  rewriteProjectInternalDependenciesToStableVersions,
328
463
  tagHasTreeseedDevMetadata,