@treeseed/sdk 0.10.27 → 0.11.0

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 (168) hide show
  1. package/README.md +207 -6
  2. package/dist/capacity-provider.d.ts +3 -1
  3. package/dist/capacity-provider.js +25 -5
  4. package/dist/control-plane.d.ts +1 -0
  5. package/dist/control-plane.js +38 -13
  6. package/dist/db/market-schema.d.ts +8860 -6172
  7. package/dist/db/market-schema.js +108 -0
  8. package/dist/db/node-sqlite.js +7 -2
  9. package/dist/hosting/apps.d.ts +12 -0
  10. package/dist/hosting/apps.js +107 -0
  11. package/dist/hosting/builtins.d.ts +25 -0
  12. package/dist/hosting/builtins.js +791 -0
  13. package/dist/hosting/contracts.d.ts +207 -0
  14. package/dist/hosting/contracts.js +0 -0
  15. package/dist/hosting/graph.d.ts +192 -0
  16. package/dist/hosting/graph.js +1106 -0
  17. package/dist/hosting/index.d.ts +4 -0
  18. package/dist/hosting/index.js +4 -0
  19. package/dist/index.d.ts +11 -4
  20. package/dist/index.js +71 -7
  21. package/dist/managed-dependencies.js +1 -2
  22. package/dist/market-client.d.ts +63 -3
  23. package/dist/market-client.js +83 -11
  24. package/dist/operations/services/bootstrap-runner.d.ts +3 -1
  25. package/dist/operations/services/bootstrap-runner.js +22 -2
  26. package/dist/operations/services/config-runtime.d.ts +10 -5
  27. package/dist/operations/services/config-runtime.js +209 -66
  28. package/dist/operations/services/deploy.d.ts +70 -7
  29. package/dist/operations/services/deploy.js +579 -64
  30. package/dist/operations/services/deployment-readiness.d.ts +30 -0
  31. package/dist/operations/services/deployment-readiness.js +175 -0
  32. package/dist/operations/services/git-workflow.d.ts +2 -1
  33. package/dist/operations/services/git-workflow.js +9 -3
  34. package/dist/operations/services/github-actions-verification.d.ts +1 -0
  35. package/dist/operations/services/github-actions-verification.js +1 -0
  36. package/dist/operations/services/github-api.js +1 -1
  37. package/dist/operations/services/github-automation.d.ts +1 -1
  38. package/dist/operations/services/github-automation.js +4 -3
  39. package/dist/operations/services/github-credentials.d.ts +13 -0
  40. package/dist/operations/services/github-credentials.js +58 -0
  41. package/dist/operations/services/hosted-service-checks.d.ts +63 -0
  42. package/dist/operations/services/hosted-service-checks.js +327 -0
  43. package/dist/operations/services/hub-provider-launch.js +3 -3
  44. package/dist/operations/services/live-hosted-service-checks.d.ts +25 -0
  45. package/dist/operations/services/live-hosted-service-checks.js +350 -0
  46. package/dist/operations/services/managed-host-security.js +1 -1
  47. package/dist/operations/services/operations-runner-smoke.d.ts +30 -0
  48. package/dist/operations/services/operations-runner-smoke.js +180 -0
  49. package/dist/operations/services/package-adapters.d.ts +95 -0
  50. package/dist/operations/services/package-adapters.js +288 -0
  51. package/dist/operations/services/package-reference-policy.d.ts +1 -0
  52. package/dist/operations/services/package-reference-policy.js +15 -2
  53. package/dist/operations/services/project-platform.d.ts +80 -22
  54. package/dist/operations/services/project-platform.js +49 -8
  55. package/dist/operations/services/project-web-monitor.js +26 -4
  56. package/dist/operations/services/railway-api.d.ts +88 -5
  57. package/dist/operations/services/railway-api.js +626 -35
  58. package/dist/operations/services/railway-deploy.d.ts +46 -40
  59. package/dist/operations/services/railway-deploy.js +261 -293
  60. package/dist/operations/services/release-candidate.d.ts +19 -0
  61. package/dist/operations/services/release-candidate.js +375 -38
  62. package/dist/operations/services/repository-save-orchestrator.d.ts +3 -1
  63. package/dist/operations/services/repository-save-orchestrator.js +279 -66
  64. package/dist/operations/services/runtime-tools.d.ts +1 -0
  65. package/dist/operations/services/runtime-tools.js +10 -9
  66. package/dist/operations/services/template-registry.js +14 -7
  67. package/dist/operations/services/verification-cache.d.ts +25 -0
  68. package/dist/operations/services/verification-cache.js +71 -0
  69. package/dist/operations/services/workspace-dependency-mode.js +9 -1
  70. package/dist/operations/services/workspace-save.js +1 -1
  71. package/dist/operations/services/workspace-tools.js +2 -1
  72. package/dist/platform/contracts.d.ts +32 -1
  73. package/dist/platform/deploy-config.js +73 -8
  74. package/dist/platform/env.yaml +163 -35
  75. package/dist/platform/environment.d.ts +1 -0
  76. package/dist/platform/environment.js +74 -5
  77. package/dist/platform/plugin.d.ts +9 -0
  78. package/dist/platform-operation-store.js +2 -2
  79. package/dist/platform-operations.js +1 -1
  80. package/dist/reconcile/bootstrap-systems.js +2 -2
  81. package/dist/reconcile/builtin-adapters.js +372 -189
  82. package/dist/reconcile/contracts.d.ts +9 -5
  83. package/dist/reconcile/desired-state.d.ts +1 -0
  84. package/dist/reconcile/desired-state.js +5 -5
  85. package/dist/reconcile/engine.d.ts +5 -2
  86. package/dist/reconcile/engine.js +53 -32
  87. package/dist/reconcile/index.d.ts +2 -0
  88. package/dist/reconcile/index.js +2 -0
  89. package/dist/reconcile/live-acceptance.d.ts +79 -0
  90. package/dist/reconcile/live-acceptance.js +1615 -0
  91. package/dist/reconcile/platform.d.ts +104 -0
  92. package/dist/reconcile/platform.js +100 -0
  93. package/dist/reconcile/state.js +4 -4
  94. package/dist/reconcile/units.js +2 -2
  95. package/dist/scripts/deployment-readiness.js +20 -0
  96. package/dist/scripts/generate-treedx-openapi-types.js +186 -0
  97. package/dist/scripts/operations-runner-smoke.js +16 -0
  98. package/dist/scripts/release-verify.js +4 -1
  99. package/dist/scripts/template-catalog.test.js +7 -7
  100. package/dist/scripts/tenant-workflow-action.js +10 -1
  101. package/dist/sdk-types.d.ts +172 -5
  102. package/dist/sdk-types.js +28 -3
  103. package/dist/sdk.d.ts +35 -24
  104. package/dist/sdk.js +186 -17
  105. package/dist/template-launch-requirements.js +9 -0
  106. package/dist/treedx/adapters.d.ts +6 -0
  107. package/dist/treedx/adapters.js +36 -0
  108. package/dist/treedx/client.d.ts +222 -0
  109. package/dist/treedx/client.js +871 -0
  110. package/dist/treedx/errors.d.ts +13 -0
  111. package/dist/treedx/errors.js +17 -0
  112. package/dist/treedx/federated-client.d.ts +27 -0
  113. package/dist/treedx/federated-client.js +158 -0
  114. package/dist/treedx/generated/openapi-types.d.ts +3558 -0
  115. package/dist/treedx/generated/openapi-types.js +0 -0
  116. package/dist/treedx/graph-adapter.d.ts +33 -0
  117. package/dist/treedx/graph-adapter.js +156 -0
  118. package/dist/treedx/index.d.ts +14 -0
  119. package/dist/treedx/index.js +48 -0
  120. package/dist/treedx/market-integration.d.ts +27 -0
  121. package/dist/treedx/market-integration.js +131 -0
  122. package/dist/treedx/ports.d.ts +166 -0
  123. package/dist/treedx/ports.js +231 -0
  124. package/dist/treedx/query-adapter.d.ts +19 -0
  125. package/dist/treedx/query-adapter.js +62 -0
  126. package/dist/treedx/registry-client.d.ts +11 -0
  127. package/dist/treedx/registry-client.js +19 -0
  128. package/dist/treedx/repository-adapter.d.ts +45 -0
  129. package/dist/treedx/repository-adapter.js +308 -0
  130. package/dist/treedx/sdk-integration.d.ts +27 -0
  131. package/dist/treedx/sdk-integration.js +63 -0
  132. package/dist/treedx/types.d.ts +1084 -0
  133. package/dist/treedx/types.js +8 -0
  134. package/dist/treedx/workspace-adapter.d.ts +27 -0
  135. package/dist/treedx/workspace-adapter.js +65 -0
  136. package/dist/treedx-backends.d.ts +218 -0
  137. package/dist/treedx-backends.js +632 -0
  138. package/dist/treedx-client.d.ts +86 -0
  139. package/dist/treedx-client.js +175 -0
  140. package/dist/treeseed/template-catalog/catalog.fixture.json +497 -138
  141. package/dist/workflow/operations.d.ts +119 -13
  142. package/dist/workflow/operations.js +309 -53
  143. package/dist/workflow-state.d.ts +13 -0
  144. package/dist/workflow-state.js +43 -26
  145. package/dist/workflow-support.d.ts +11 -3
  146. package/dist/workflow-support.js +67 -3
  147. package/dist/workflow.d.ts +5 -0
  148. package/drizzle/market/0004_treedx_market_integration.sql +99 -0
  149. package/package.json +34 -3
  150. package/templates/github/deploy-web.workflow.yml +39 -6
  151. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.d.ts +0 -3
  152. package/dist/treeseed/template-catalog/templates/starter-basic/template/astro.config.ts +0 -6
  153. package/dist/treeseed/template-catalog/templates/starter-basic/template/package.json +0 -35
  154. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/api/server.js +0 -4
  155. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/config.yaml +0 -65
  156. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/decisions/adopt-initial-proposal-loop.mdx +0 -22
  157. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/empty/.gitkeep +0 -1
  158. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/knowledge/handbook/index.mdx +0 -11
  159. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/pages/welcome.mdx +0 -11
  160. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/people/starter-steward.mdx +0 -11
  161. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content/proposals/establish-initial-proposal-loop.mdx +0 -17
  162. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.d.ts +0 -1
  163. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/content.config.ts +0 -3
  164. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/env.yaml +0 -1
  165. package/dist/treeseed/template-catalog/templates/starter-basic/template/src/manifest.yaml +0 -26
  166. package/dist/treeseed/template-catalog/templates/starter-basic/template/treeseed.site.yaml +0 -74
  167. package/dist/treeseed/template-catalog/templates/starter-basic/template/tsconfig.json +0 -9
  168. package/dist/treeseed/template-catalog/templates/starter-basic/template.config.json +0 -103
package/README.md CHANGED
@@ -4,6 +4,21 @@
4
4
 
5
5
  For most consumers, the right entrypoint is `AgentSdk`.
6
6
 
7
+ Use the SDK when you are writing automation, services, scripts, agents, or package internals that need Treeseed data, graph, workflow, config, reconciliation, hosting, package, or TreeDX integration primitives. Use the CLI when you want an operator command. Use Admin when you want a browser UI. Use API when you need the deployed backend service. Use UI when you need reusable components.
8
+
9
+ ## How SDK Fits With Treeseed
10
+
11
+ The SDK is the shared platform substrate used by:
12
+
13
+ - `@treeseed/core` for site runtime, content, plugin, and hosting integration
14
+ - `@treeseed/admin` for admin contracts, view models, API facades, and platform primitives
15
+ - `@treeseed/api` for backend contracts, reconciliation, operation state, and shared data models
16
+ - `@treeseed/cli` for workflow, config, hosting, release, and reconciliation commands
17
+ - `@treeseed/agent` for provider contracts and runtime coordination
18
+ - root `@treeseed/market` for tenant config, content, and hosted workflow integration
19
+
20
+ The SDK is not a UI package, admin portal, backend server, CLI parser, capacity-provider runtime, or ecommerce implementation. See the root [Package Ownership](../../docs/package-ownership.md) guide for the full system map.
21
+
7
22
  ## Which Surface Should I Use?
8
23
 
9
24
  Treeseed exposes three public SDK surfaces, but they are not peers:
@@ -24,9 +39,44 @@ If you are unsure, use `AgentSdk`.
24
39
  - operational runtime state such as messages, runs, cursors, and leases
25
40
  - control-plane orchestration for work days, tasks, task events, graph runs, and reports
26
41
  - provider-neutral capacity scheduling contracts for task classification, admission, execution profiles, routing, estimates, planning proposals, attention load, utility, predictive reserve, hybrid execution, checkpoints, and usage actuals
42
+ - hosting graph compilation, deployment readiness, live hosted-service checks, Treeseed runner smoke helpers, and verification cache support for Treeseed workflows
27
43
  - graph-first context retrieval through `parseGraphDsl()`, `resolveSeeds()`, `queryGraph()`, and `buildContextPack()`
28
44
  - agent scoping through `scopeForAgent()`
29
45
 
46
+ ## Workflow And Hosting Support
47
+
48
+ The SDK owns the shared implementation behind the fail-fast `trsd` deployment workflow.
49
+ It also owns the canonical reconciliation platform for desired-state infrastructure. See the root workspace `docs/reconciliation-platform.md` for the full contract.
50
+
51
+ Current workflow-support exports include:
52
+
53
+ ```ts
54
+ import {
55
+ collectTreeseedDeploymentReadiness,
56
+ collectTreeseedLiveHostedServiceChecks,
57
+ formatTreeseedReadinessReport,
58
+ runTreeseedOperationsRunnerSmoke,
59
+ } from '@treeseed/sdk/workflow-support';
60
+ ```
61
+
62
+ These helpers are used by:
63
+
64
+ - `trsd ready <local|staging|prod>`
65
+ - `trsd hosting plan|apply|verify --environment <env> --service <id>`
66
+ - `trsd audit hosting --environment <env> --live`
67
+ - `trsd doctor --live --hosted-services`
68
+ - `trsd operations smoke --environment <env> --service operationsRunner`
69
+ - `trsd stage|release --verify-deployed-resources`
70
+
71
+ For the API app, the expected hosted backend services are the API service, indexed Treeseed operations runner, PostgreSQL, and public TreeDX federation nodes owned by `packages/api`. The root web app remains a web UI and `/v1/*` proxy/client surface, with admin routes contributed by `@treeseed/admin` and visual primitives contributed by `@treeseed/ui`.
72
+
73
+ Reconciliation guarantees:
74
+
75
+ - command surfaces compile desired resources before provider mutation
76
+ - cached state can locate resources but live observation proves readiness
77
+ - hosted apply cannot report `ok: true` when live postconditions fail
78
+ - adapter reports use `desiredGraph`, `observedGraph`, `stateGraph`, `diff`, `actions`, `postconditions`, `blockedDrift`, `providerLimitations`, `liveVerification`, and `ok`
79
+
30
80
  ## Install
31
81
 
32
82
  ```bash
@@ -61,6 +111,16 @@ const sdk = AgentSdk.createLocal({
61
111
  });
62
112
  ```
63
113
 
114
+ ## TreeDX Content Repository
115
+
116
+ TreeDX is the generic repository service used by Treeseed when TreeDX service configuration is available. The SDK is the Treeseed integration and client layer: it configures the TreeDX portfolio, maps Treeseed model registry behavior onto generic repository/ref/path/frontmatter/body/query requests, and keeps product semantics outside TreeDX. The API package may host public TreeDX federation nodes as part of backend reconciliation.
117
+
118
+ Project site code and optional project repositories remain local filesystem/git
119
+ workspace concerns by default. Use `contentRepository: { adapter: 'local' }` or
120
+ `AgentSdk.createLocal()` for explicit local content behavior.
121
+
122
+ See [TreeDX Content Repository](./docs/treedx-content-repository.md).
123
+
64
124
  ## Preferred Graph Workflow
65
125
 
66
126
  The preferred graph API for new integrations is:
@@ -91,7 +151,7 @@ The public `ctx` syntax is:
91
151
 
92
152
  ```text
93
153
  ctx <target>
94
- [for <stage>]
154
+ [for <focus>]
95
155
  [in <scope>]
96
156
  [via <relation[,relation...]>]
97
157
  [depth <0-3>]
@@ -103,9 +163,150 @@ ctx <target>
103
163
 
104
164
  The old `key=value` graph DSL is no longer supported.
105
165
 
166
+ ## TreeDX Remote Repository Mode
167
+
168
+ TreeDX support is opt-in. Local SDK behavior remains the default.
169
+
170
+ Use the low-level TreeDX client when you want direct repository, workspace, query, graph, registry, or context calls:
171
+
172
+ ```ts
173
+ import { TreeDxClient } from '@treeseed/sdk/treedx';
174
+
175
+ const treeDx = new TreeDxClient({
176
+ baseUrl: 'http://localhost:4000',
177
+ token: process.env.TREEDX_TOKEN,
178
+ repoId: 'repo_123',
179
+ });
180
+
181
+ const whoami = await treeDx.whoami();
182
+ const file = await treeDx.readRepositoryFile({
183
+ path: 'docs/readme.md',
184
+ parseFrontmatter: true,
185
+ });
186
+ ```
187
+
188
+ `AgentSdk` can delegate content-backed model and graph calls to TreeDX when configured explicitly:
189
+
190
+ ```ts
191
+ import { AgentSdk, TreeDxClient } from '@treeseed/sdk';
192
+
193
+ const treeDx = new TreeDxClient({
194
+ baseUrl: 'http://localhost:4000',
195
+ token: process.env.TREEDX_TOKEN,
196
+ repoId: 'repo_123',
197
+ });
198
+
199
+ const sdk = new AgentSdk({
200
+ repoRoot: process.cwd(),
201
+ treeDx: {
202
+ enabled: true,
203
+ client: treeDx,
204
+ repoId: 'repo_123',
205
+ defaultRef: 'refs/heads/main',
206
+ },
207
+ });
208
+
209
+ const docs = await sdk.search({
210
+ model: 'knowledge',
211
+ filters: [{ field: 'status', op: 'eq', value: 'published' }],
212
+ });
213
+ ```
214
+
215
+ TreeDX mode keeps TreeSeed model semantics in the SDK model registry. TreeDX receives generic repository/ref/path/frontmatter/body/query requests and returns generic repository/file/query/graph results.
216
+
217
+ TreeDX auth, policy, audit, and federation helpers are available on the same client:
218
+
219
+ ```ts
220
+ const mode = await treeDx.authMode();
221
+ const scope = await treeDx.effectiveScope({ repoId: 'repo_123' });
222
+
223
+ await treeDx.putCapabilityGrant({
224
+ actorId: 'actor_agent',
225
+ tenantId: 'tenant_demo',
226
+ repoIds: ['repo_123'],
227
+ capabilities: ['files:read', 'files:search'],
228
+ refs: ['refs/heads/main'],
229
+ paths: ['docs/**'],
230
+ });
231
+
232
+ const audit = await treeDx.listAuditEvents({
233
+ repoId: 'repo_123',
234
+ eventType: 'repo.query_executed',
235
+ limit: 25,
236
+ });
237
+
238
+ const plan = await treeDx.planFederatedQuery({
239
+ repoIds: ['repo_123'],
240
+ capabilities: ['files:search'],
241
+ paths: { repo_123: ['docs/**'] },
242
+ });
243
+
244
+ const search = await treeDx.federatedSearch({
245
+ repoIds: ['repo_123'],
246
+ refs: { repo_123: 'refs/heads/main' },
247
+ paths: { repo_123: ['docs/**'] },
248
+ query: 'release',
249
+ includeErrors: true,
250
+ });
251
+ ```
252
+
253
+ Federation planning performs scope reduction before execution. The SDK delegates global execution to TreeDX instead of fanning out across every node and filtering locally.
254
+
255
+ Snapshot, artifact, mirror sync, and migration helpers are also available on `TreeDxClient`:
256
+
257
+ ```ts
258
+ const snapshot = await treeDx.buildSnapshot({
259
+ ref: 'refs/heads/main',
260
+ kind: 'repository_snapshot',
261
+ paths: ['docs/**'],
262
+ includeGraph: true,
263
+ });
264
+
265
+ const artifact = await treeDx.exportArtifact({
266
+ snapshotId: snapshot.snapshotId,
267
+ });
268
+
269
+ const download = await treeDx.downloadArtifact({
270
+ snapshotId: snapshot.snapshotId,
271
+ });
272
+
273
+ await treeDx.syncMirror({
274
+ mirrorId: 'mirror_123',
275
+ remoteName: 'origin',
276
+ });
277
+
278
+ await treeDx.createMigration({
279
+ targetNodeId: 'node_mirror',
280
+ mode: 'primary_transfer',
281
+ dryRun: true,
282
+ requireMirrorSynced: false,
283
+ });
284
+
285
+ await treeDx.ready();
286
+ await treeDx.deepHealth();
287
+ await treeDx.metrics();
288
+ ```
289
+
290
+ `downloadArtifact()` returns an `ArrayBuffer` plus content type, filename, checksum, and snapshot headers. These APIs are generic TreeDX repository operations; TreeSeed package or release semantics are not encoded in TreeDX.
291
+
292
+ Mocked end-to-end TreeDX contract tests prove the SDK can drive the TreeDX repository loop without an agent-side clone when `contentPathMap` is supplied:
293
+
294
+ ```bash
295
+ npx vitest run --config ./vitest.config.ts test/utils/treedx-e2e-contract.test.ts
296
+ ```
297
+
298
+ The optional live contract command reports `not configured` and exits
299
+ successfully unless all of these are set:
300
+
301
+ ```text
302
+ TREEDX_LIVE_URL
303
+ TREEDX_LIVE_TOKEN
304
+ TREEDX_LIVE_REPO_ID
305
+ ```
306
+
106
307
  ## Capacity Scheduling Contracts
107
308
 
108
- The SDK owns the provider-neutral capacity runtime helpers used by the agent manager, workers, and market control plane. These helpers keep work estimation separate from provider cost by normalizing `taskSignature + executionProfileId` estimates, then routing against grants, provider lanes, quality requirements, quota/congestion pressure, attention/context saturation, utility, predictive reserve, and hybrid phase metadata.
309
+ The SDK owns the provider-neutral capacity runtime helpers used by the agent manager, workers, and market control plane. These helpers keep work estimation separate from provider cost by normalizing `taskSignature + executionProfileId` estimates, then routing against grants, provider lanes, quality requirements, quota/congestion pressure, attention/context saturation, utility, predictive reserve, and hybrid execution metadata.
109
310
 
110
311
  Capacity records remain metadata-compatible: advanced scheduling data lives in task payload JSON, routing decision candidates/scores, reservation metadata, capacity plan metadata, checkpoint artifacts, and usage actual metadata. Missing metadata is neutral, so older callers continue to use the credit-only behavior.
111
312
 
@@ -165,10 +366,10 @@ const scoped = sdk.scopeForAgent({
165
366
 
166
367
  ## Reference Docs
167
368
 
168
- - [SDK Interface Reference](/home/adrian/Projects/treeseed/market/src/content/knowledge/sdk/interface-reference.mdx)
169
- - [Graph API Guide](/home/adrian/Projects/treeseed/market/src/content/knowledge/sdk/graph-api-guide.mdx)
170
- - [ctx Query Language](/home/adrian/Projects/treeseed/market/src/content/knowledge/sdk/ctx-query-language.mdx)
171
- - [How ctx Works](/home/adrian/Projects/treeseed/market/src/content/knowledge/sdk/ctx-query-engine.mdx)
369
+ - [SDK Interface Reference](../../src/content/knowledge/sdk/interface-reference.mdx)
370
+ - [Graph API Guide](../../src/content/knowledge/sdk/graph-api-guide.mdx)
371
+ - [ctx Query Language](../../src/content/knowledge/sdk/ctx-query-language.mdx)
372
+ - [How ctx Works](../../src/content/knowledge/sdk/ctx-query-engine.mdx)
172
373
 
173
374
  ## Other Public Capabilities
174
375
 
@@ -1,4 +1,5 @@
1
1
  import type { NativeUsageObservation } from './sdk-types.ts';
2
+ import type { ProjectRepositoryTopology } from './sdk-types.ts';
2
3
  export declare const CAPACITY_PROVIDER_ENDPOINTS: {
3
4
  readonly register: "/v1/provider/register";
4
5
  readonly heartbeat: "/v1/provider/heartbeat";
@@ -12,7 +13,7 @@ export declare const CAPACITY_PROVIDER_ENDPOINTS: {
12
13
  readonly reports: "/v1/provider/reports";
13
14
  };
14
15
  export declare const CAPACITY_PROVIDER_SCOPES: readonly ["provider:register", "provider:heartbeat", "provider:portfolio:read", "provider:tasks:claim", "provider:tasks:update", "provider:usage:report", "provider:reports:write", "provider:capabilities:write"];
15
- export declare const CAPACITY_PROVIDER_ENV_KEYS: readonly ["TREESEED_MARKET_URL", "TREESEED_MARKET_ID", "TREESEED_CAPACITY_PROVIDER_API_KEY", "TREESEED_PROVIDER_HOST_DATA_DIR", "TREESEED_PROVIDER_DATA_DIR", "TREESEED_PROVIDER_API_PORT", "TREESEED_PROVIDER_HOST_API_PORT", "TREESEED_PROVIDER_ENVIRONMENT", "TREESEED_PROVIDER_CAPABILITIES_FILE", "TREESEED_PROVIDER_BUDGET_FILE", "TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS", "TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS", "TREESEED_PROVIDER_DAILY_CREDIT_BUDGET", "TREESEED_PROVIDER_MONTHLY_CREDIT_BUDGET", "TREESEED_PROVIDER_STARTUP_MODE", "TREESEED_CODEX_AUTH_FILE", "TREESEED_CODEX_AUTH_JSON_B64", "TREESEED_CODEX_AUTH_OVERWRITE"];
16
+ export declare const CAPACITY_PROVIDER_ENV_KEYS: readonly ["TREESEED_MARKET_URL", "TREESEED_MANAGER_ID", "TREESEED_CAPACITY_PROVIDER_API_KEY", "TREESEED_PROVIDER_HOST_DATA_DIR", "TREESEED_PROVIDER_DATA_DIR", "TREESEED_PROVIDER_API_PORT", "TREESEED_PROVIDER_HOST_API_PORT", "TREESEED_PROVIDER_ENVIRONMENT", "TREESEED_PROVIDER_CAPABILITIES_FILE", "TREESEED_PROVIDER_BUDGET_FILE", "TREESEED_PROVIDER_MAX_CONCURRENT_WORKDAYS", "TREESEED_PROVIDER_MAX_CONCURRENT_RUNNERS", "TREESEED_PROVIDER_DAILY_CREDIT_BUDGET", "TREESEED_PROVIDER_MONTHLY_CREDIT_BUDGET", "TREESEED_PROVIDER_STARTUP_MODE", "TREESEED_CODEX_AUTH_FILE", "TREESEED_CODEX_AUTH_JSON_B64", "TREESEED_CODEX_AUTH_OVERWRITE"];
16
17
  export type CapacityProviderScope = (typeof CAPACITY_PROVIDER_SCOPES)[number];
17
18
  export type CapacityProviderEnvironmentName = 'local' | 'staging' | 'prod' | 'production' | string;
18
19
  export type CapacityProviderLaunchMode = 'self_hosted' | 'managed_market_host' | 'connected_host';
@@ -154,6 +155,7 @@ export interface CapacityProviderPortfolioProject {
154
155
  submodulePath?: string | null;
155
156
  webUrl?: string | null;
156
157
  };
158
+ repositoryTopology?: ProjectRepositoryTopology;
157
159
  agentSpecs: {
158
160
  root: string;
159
161
  testsRoot: string;
@@ -32,7 +32,7 @@ const CAPACITY_PROVIDER_SCOPES = [
32
32
  ];
33
33
  const CAPACITY_PROVIDER_ENV_KEYS = [
34
34
  "TREESEED_MARKET_URL",
35
- "TREESEED_MARKET_ID",
35
+ "TREESEED_MANAGER_ID",
36
36
  "TREESEED_CAPACITY_PROVIDER_API_KEY",
37
37
  "TREESEED_PROVIDER_HOST_DATA_DIR",
38
38
  "TREESEED_PROVIDER_DATA_DIR",
@@ -158,6 +158,26 @@ function assertCapacityProviderPortfolioManifest(value) {
158
158
  requireString(project, "slug", `Capacity provider portfolio project ${index}`);
159
159
  requireString(project, "name", `Capacity provider portfolio project ${index}`);
160
160
  if (!isRecord(project.repository)) throw new Error(`Capacity provider portfolio project ${index} is missing repository.`);
161
+ if (project.repositoryTopology !== void 0) {
162
+ if (!isRecord(project.repositoryTopology)) {
163
+ throw new Error(`Capacity provider portfolio project ${index} repositoryTopology must be an object.`);
164
+ }
165
+ if (!isRecord(project.repositoryTopology.contentRepository)) {
166
+ throw new Error(`Capacity provider portfolio project ${index} repositoryTopology is missing contentRepository.`);
167
+ }
168
+ if (project.repositoryTopology.contentRepository.accessMode !== "treedx") {
169
+ throw new Error(`Capacity provider portfolio project ${index} contentRepository must use treedx access.`);
170
+ }
171
+ if (!isRecord(project.repositoryTopology.siteRepository)) {
172
+ throw new Error(`Capacity provider portfolio project ${index} repositoryTopology is missing siteRepository.`);
173
+ }
174
+ if (project.repositoryTopology.siteRepository.accessMode !== "filesystem") {
175
+ throw new Error(`Capacity provider portfolio project ${index} siteRepository must use filesystem access.`);
176
+ }
177
+ if (project.repositoryTopology.projectRepository !== void 0 && project.repositoryTopology.projectRepository !== null && (!isRecord(project.repositoryTopology.projectRepository) || project.repositoryTopology.projectRepository.accessMode !== "filesystem")) {
178
+ throw new Error(`Capacity provider portfolio project ${index} projectRepository must use filesystem access.`);
179
+ }
180
+ }
161
181
  if (!isRecord(project.agentSpecs)) throw new Error(`Capacity provider portfolio project ${index} is missing agentSpecs.`);
162
182
  if (!isRecord(project.workPolicy)) throw new Error(`Capacity provider portfolio project ${index} is missing workPolicy.`);
163
183
  }
@@ -165,13 +185,13 @@ function assertCapacityProviderPortfolioManifest(value) {
165
185
  function resolveCapacityProviderEnvironment(input) {
166
186
  const env = {
167
187
  TREESEED_MARKET_URL: normalizeBaseUrl(input.marketUrl),
168
- TREESEED_MARKET_ID: input.marketId.trim(),
188
+ TREESEED_MANAGER_ID: input.marketId.trim(),
169
189
  TREESEED_CAPACITY_PROVIDER_API_KEY: input.apiKey.trim(),
170
190
  TREESEED_PROVIDER_DATA_DIR: input.providerDataDir ?? "/data",
171
191
  TREESEED_PROVIDER_API_PORT: stringValue(input.providerApiPort, "3100"),
172
192
  TREESEED_PROVIDER_ENVIRONMENT: input.providerEnvironment ?? "local"
173
193
  };
174
- if (!env.TREESEED_MARKET_ID) throw new Error("Capacity provider Market ID is required.");
194
+ if (!env.TREESEED_MANAGER_ID) throw new Error("Capacity provider Market ID is required.");
175
195
  if (!env.TREESEED_CAPACITY_PROVIDER_API_KEY) throw new Error("Capacity provider API key is required.");
176
196
  if (input.providerHostDataDir) env.TREESEED_PROVIDER_HOST_DATA_DIR = input.providerHostDataDir;
177
197
  if (input.capabilitiesFile) env.TREESEED_PROVIDER_CAPABILITIES_FILE = input.capabilitiesFile;
@@ -230,7 +250,7 @@ function resolveCapacityProviderLaunchEnvironment(input = {}) {
230
250
  }
231
251
  const required = [
232
252
  "TREESEED_MARKET_URL",
233
- "TREESEED_MARKET_ID",
253
+ "TREESEED_MANAGER_ID",
234
254
  ...diagnostic ? [] : ["TREESEED_CAPACITY_PROVIDER_API_KEY"],
235
255
  "TREESEED_PROVIDER_HOST_DATA_DIR"
236
256
  ];
@@ -262,7 +282,7 @@ function persistCapacityProviderConnectionToTreeseedConfig(input) {
262
282
  const entryById = new Map(registryEntries.map((entry) => [entry.id, entry]));
263
283
  const keys = [
264
284
  "TREESEED_MARKET_URL",
265
- "TREESEED_MARKET_ID",
285
+ "TREESEED_MANAGER_ID",
266
286
  "TREESEED_CAPACITY_PROVIDER_API_KEY",
267
287
  "TREESEED_PROVIDER_HOST_DATA_DIR",
268
288
  "TREESEED_PROVIDER_ENVIRONMENT"
@@ -91,6 +91,7 @@ export interface ControlPlaneReporterOptions {
91
91
  baseUrl?: string | null;
92
92
  runnerToken?: string | null;
93
93
  fetchImpl?: typeof fetch;
94
+ requestTimeoutMs?: number | null;
94
95
  }
95
96
  export interface ResolveControlPlaneReporterOptions extends ControlPlaneReporterOptions {
96
97
  hostingKind?: TreeseedHostingKind | null;
@@ -21,8 +21,8 @@ function resolveReporterKind(options) {
21
21
  if (hostingKind === "self_hosted_project" && registration === "optional") {
22
22
  return "market_http";
23
23
  }
24
- if (hostingKind === "market_control_plane") {
25
- return normalizeUrl(options.baseUrl ?? process.env.TREESEED_MARKET_API_BASE_URL ?? options.deployConfig?.hosting?.marketBaseUrl) ? "self_http" : "noop";
24
+ if (hostingKind === "treeseed_control_plane") {
25
+ return normalizeUrl(options.baseUrl ?? process.env.TREESEED_API_BASE_URL ?? options.deployConfig?.hosting?.marketBaseUrl) ? "self_http" : "noop";
26
26
  }
27
27
  return "noop";
28
28
  }
@@ -60,13 +60,14 @@ class NoopControlPlaneReporter {
60
60
  }
61
61
  }
62
62
  class HttpControlPlaneReporter {
63
- constructor(kind, projectId, baseUrl, runnerToken, fetchImpl = fetch) {
63
+ constructor(kind, projectId, baseUrl, runnerToken, fetchImpl = fetch, requestTimeoutMs) {
64
64
  this.kind = kind;
65
65
  this.projectId = projectId;
66
66
  this.baseUrl = baseUrl;
67
67
  this.runnerToken = runnerToken;
68
68
  this.fetchImpl = fetchImpl;
69
69
  this.enabled = Boolean(this.projectId && this.baseUrl && this.runnerToken);
70
+ this.requestTimeoutMs = normalizeRequestTimeoutMs(requestTimeoutMs);
70
71
  }
71
72
  kind;
72
73
  projectId;
@@ -74,18 +75,32 @@ class HttpControlPlaneReporter {
74
75
  runnerToken;
75
76
  fetchImpl;
76
77
  enabled;
78
+ requestTimeoutMs;
77
79
  async request(method, pathname, body) {
78
80
  if (!this.enabled || !this.baseUrl || !this.runnerToken) {
79
81
  return null;
80
82
  }
81
- const response = await this.fetchImpl(new URL(pathname, this.baseUrl), {
82
- method,
83
- headers: {
84
- authorization: `Bearer ${this.runnerToken}`,
85
- "content-type": "application/json"
86
- },
87
- body: body === void 0 ? void 0 : JSON.stringify(body)
88
- });
83
+ const controller = new AbortController();
84
+ const timeout = setTimeout(() => controller.abort(), this.requestTimeoutMs);
85
+ let response;
86
+ try {
87
+ response = await this.fetchImpl(new URL(pathname, this.baseUrl), {
88
+ method,
89
+ headers: {
90
+ authorization: `Bearer ${this.runnerToken}`,
91
+ "content-type": "application/json"
92
+ },
93
+ body: body === void 0 ? void 0 : JSON.stringify(body),
94
+ signal: controller.signal
95
+ });
96
+ } catch (error) {
97
+ if (controller.signal.aborted) {
98
+ throw new Error(`Control-plane request timed out for ${pathname} after ${this.requestTimeoutMs}ms.`);
99
+ }
100
+ throw error;
101
+ } finally {
102
+ clearTimeout(timeout);
103
+ }
89
104
  if (!response.ok) {
90
105
  throw new Error(`Control-plane request failed for ${pathname}: ${response.status} ${response.statusText}`);
91
106
  }
@@ -154,6 +169,16 @@ class HttpControlPlaneReporter {
154
169
  return this.request("POST", `/v1/projects/${this.projectId}/runner/approval-requests`, input);
155
170
  }
156
171
  }
172
+ function normalizeRequestTimeoutMs(value) {
173
+ if (Number.isFinite(value) && Number(value) > 0) {
174
+ return Number(value);
175
+ }
176
+ const fromEnv = Number.parseInt(String(process.env.TREESEED_CONTROL_PLANE_REQUEST_TIMEOUT_MS ?? ""), 10);
177
+ if (Number.isFinite(fromEnv) && fromEnv > 0) {
178
+ return fromEnv;
179
+ }
180
+ return 15e3;
181
+ }
157
182
  function createControlPlaneReporter(options = {}) {
158
183
  const kind = resolveReporterKind(options);
159
184
  if (kind === "noop") {
@@ -163,13 +188,13 @@ function createControlPlaneReporter(options = {}) {
163
188
  options.projectId ?? process.env.TREESEED_PROJECT_ID ?? options.deployConfig?.hosting?.projectId ?? ""
164
189
  ).trim() || null;
165
190
  const baseUrl = normalizeUrl(
166
- options.baseUrl ?? process.env.TREESEED_MARKET_API_BASE_URL ?? options.deployConfig?.hosting?.marketBaseUrl ?? null
191
+ options.baseUrl ?? process.env.TREESEED_API_BASE_URL ?? options.deployConfig?.hosting?.marketBaseUrl ?? null
167
192
  );
168
193
  const runnerToken = String(options.runnerToken ?? process.env.TREESEED_PROJECT_RUNNER_TOKEN ?? "").trim() || null;
169
194
  if (!projectId || !baseUrl || !runnerToken) {
170
195
  return new NoopControlPlaneReporter();
171
196
  }
172
- return new HttpControlPlaneReporter(kind, projectId, baseUrl, runnerToken, options.fetchImpl);
197
+ return new HttpControlPlaneReporter(kind, projectId, baseUrl, runnerToken, options.fetchImpl, options.requestTimeoutMs);
173
198
  }
174
199
  export {
175
200
  createControlPlaneReporter