@treeseed/agent 0.8.5 → 0.8.7
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/README.md +126 -139
- package/dist/agents/adapters/notification.d.ts +1 -1
- package/dist/agents/kernel/agent-kernel.d.ts +1 -1
- package/dist/agents/registry.js +57 -6
- package/dist/agents/spec-loader.d.ts +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/scripts/.ts-run-1778487652250-xq14ouuyiie.js +25 -0
- package/dist/scripts/.ts-run-1778487657087-47rihuztkz3.js +100 -0
- package/dist/scripts/build-dist.js +8 -12
- package/dist/scripts/prepare.js +14 -0
- package/dist/scripts/release-verify.js +28 -0
- package/dist/scripts/run-ts.js +45 -0
- package/dist/scripts/verify-driver.js +34 -0
- package/dist/services/common.js +1 -1
- package/dist/services/manager.d.ts +6 -6
- package/dist/services/manager.js +1 -4
- package/dist/services/workday-manager.d.ts +10 -10
- package/dist/services/workday-report.d.ts +4 -4
- package/dist/services/workday-start.d.ts +4 -4
- package/package.json +6 -5
- package/dist/scripts/assert-release-tag-version.d.ts +0 -1
- package/dist/scripts/build-dist.d.ts +0 -1
- package/dist/scripts/package-tools.d.ts +0 -1
- package/dist/scripts/publish-package.d.ts +0 -1
- package/dist/scripts/release-verify.d.ts +0 -1
- package/dist/scripts/test-smoke.d.ts +0 -1
- package/dist/scripts/treeseed-agent-api.d.ts +0 -2
- package/dist/scripts/treeseed-agent-service.d.ts +0 -2
- package/dist/scripts/treeseed-agents.d.ts +0 -2
package/README.md
CHANGED
|
@@ -1,92 +1,81 @@
|
|
|
1
1
|
# `@treeseed/agent`
|
|
2
2
|
|
|
3
|
-
Treeseed
|
|
3
|
+
Treeseed backend API and processing framework package.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
`@treeseed/agent` owns the reusable processing plane for Treeseed. It provides the Hono API foundation, agent runtime, manager service, worker runner service, cron-style workday entrypoints, processing-host templates, and processing env registry. It depends on `@treeseed/sdk` for contracts, stores, deployment primitives, and provider-neutral runtime helpers. It does not depend on `@treeseed/core`.
|
|
6
6
|
|
|
7
|
-
##
|
|
7
|
+
## Package Role
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
- `manager` for work-day orchestration, graph ownership, and context assembly
|
|
11
|
-
- `worker` for bounded task execution against Cloudflare Queue deliveries
|
|
12
|
-
- `workday-start` and `workday-report` for cron-friendly kickoff and reporting
|
|
13
|
-
- helper scripts for running a local manager against a deployed Cloudflare site and gateway
|
|
9
|
+
The Treeseed package split is:
|
|
14
10
|
|
|
15
|
-
|
|
11
|
+
- `@treeseed/sdk`: shared contracts, stores, graph/query/runtime primitives, deployment config, and registry merge runtime
|
|
12
|
+
- `@treeseed/core`: Astro/Starlight web framework, content, forms, web cache, and web-only Cloudflare integration
|
|
13
|
+
- `@treeseed/agent`: backend API, agent runtime, processing services, processing-host manifests, and capacity-provider health/reporting
|
|
14
|
+
- `@treeseed/market`: product app that composes `@treeseed/core`, `@treeseed/agent`, and `@treeseed/sdk`
|
|
16
15
|
|
|
17
|
-
|
|
16
|
+
Ordinary hosted projects should not need their own API, manager, worker, or workday services. They reference assigned processing capacity. Market and team-owned processing hosts use this package to run that capacity.
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
2. Cloudflare site + local manager on your laptop
|
|
21
|
-
3. Cloudflare control plane + Railway manager/worker services
|
|
18
|
+
## Public Surfaces
|
|
22
19
|
|
|
23
|
-
|
|
20
|
+
Package exports:
|
|
24
21
|
|
|
25
|
-
|
|
22
|
+
- `@treeseed/agent`
|
|
23
|
+
- `@treeseed/agent/api`
|
|
24
|
+
- `@treeseed/agent/api/app`
|
|
25
|
+
- `@treeseed/agent/api/auth/d1-provider`
|
|
26
|
+
- `@treeseed/agent/services/manager`
|
|
27
|
+
- `@treeseed/agent/services/worker`
|
|
28
|
+
- `@treeseed/agent/services/remote-runner`
|
|
29
|
+
- `@treeseed/agent/services/workday-manager`
|
|
30
|
+
- `@treeseed/agent/services/workday-start`
|
|
31
|
+
- `@treeseed/agent/services/workday-report`
|
|
32
|
+
- `@treeseed/agent/runtime-types`
|
|
33
|
+
- `@treeseed/agent/cli`
|
|
34
|
+
- `@treeseed/agent/contracts/messages`
|
|
35
|
+
- `@treeseed/agent/contracts/run`
|
|
26
36
|
|
|
27
|
-
|
|
28
|
-
- npm
|
|
29
|
-
- a Treeseed tenant repository for runtime commands such as `doctor` and `start`
|
|
37
|
+
Published binaries:
|
|
30
38
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
npm install @treeseed/agent @treeseed/sdk
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
## Build And Test
|
|
39
|
+
- `treeseed-agents`
|
|
40
|
+
- `treeseed-agent-api`
|
|
41
|
+
- `treeseed-agent-service`
|
|
38
42
|
|
|
39
|
-
|
|
40
|
-
npm install
|
|
41
|
-
npm run build
|
|
42
|
-
npm test
|
|
43
|
-
npm run release:verify
|
|
44
|
-
```
|
|
43
|
+
The API foundation exposes `createTreeseedApiApp`, `createTreeseedApiRouter`, `createTreeseedNodeServer`, and the `TreeseedApiExtension` contract. Market-specific routes should mount through extensions owned by the market app.
|
|
45
44
|
|
|
46
|
-
|
|
45
|
+
## Source Layout
|
|
47
46
|
|
|
48
|
-
|
|
47
|
+
- `src/api`: Hono API app, auth providers, base routes, runtime provider resolution, and Node/Railway server helpers
|
|
48
|
+
- `src/agents`: agent kernel, handler registry, adapters, contracts, spec normalization, CLI, and test harnesses
|
|
49
|
+
- `src/services`: manager, worker, workday, remote runner, worker capacity, scaler, and shared processing service helpers
|
|
50
|
+
- `src/env.yaml`: processing/API env registry entries owned by this package
|
|
51
|
+
- `templates/github/deploy-processing.workflow.yml`: reusable processing-plane workflow template
|
|
49
52
|
|
|
50
|
-
|
|
51
|
-
npm run build
|
|
52
|
-
npm run dev:manager
|
|
53
|
-
```
|
|
53
|
+
Tests mirror the source domains under `test/api` and `test/services`, with package-shape checks under `test/package`.
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
## Install
|
|
56
56
|
|
|
57
57
|
```bash
|
|
58
|
-
npm
|
|
59
|
-
npm run dev:workday-start
|
|
60
|
-
npm run dev:workday-report
|
|
58
|
+
npm install @treeseed/agent @treeseed/sdk
|
|
61
59
|
```
|
|
62
60
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
Run the CLI from a Treeseed tenant repository root, or set `TREESEED_TENANT_ROOT` to point at one.
|
|
61
|
+
For workspace development, work from this package root:
|
|
66
62
|
|
|
67
63
|
```bash
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
64
|
+
npm install
|
|
65
|
+
npm run build
|
|
66
|
+
npm test
|
|
67
|
+
npm run verify:local
|
|
71
68
|
```
|
|
72
69
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
- `doctor`
|
|
76
|
-
- `run-agent <slug>`
|
|
77
|
-
- `drain-messages`
|
|
78
|
-
- `release-leases`
|
|
79
|
-
- `replay-message <id>`
|
|
80
|
-
- `start`
|
|
81
|
-
|
|
82
|
-
## Service Commands
|
|
70
|
+
## Development Commands
|
|
83
71
|
|
|
84
|
-
|
|
72
|
+
Source entrypoints:
|
|
85
73
|
|
|
86
74
|
- `npm run dev:manager`
|
|
87
75
|
- `npm run dev:worker`
|
|
88
76
|
- `npm run dev:workday-start`
|
|
89
77
|
- `npm run dev:workday-report`
|
|
78
|
+
- `npm run dev:remote-runner`
|
|
90
79
|
|
|
91
80
|
Built entrypoints:
|
|
92
81
|
|
|
@@ -95,104 +84,102 @@ Built entrypoints:
|
|
|
95
84
|
- `npm run start:workday-start`
|
|
96
85
|
- `npm run start:workday-report`
|
|
97
86
|
|
|
98
|
-
Hybrid
|
|
87
|
+
Hybrid local helper:
|
|
99
88
|
|
|
100
89
|
- `npm run start:local-manager-cloudflare`
|
|
101
90
|
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
Use this when:
|
|
105
|
-
|
|
106
|
-
- your site is deployed on Cloudflare
|
|
107
|
-
- your gateway Worker is deployed on Cloudflare
|
|
108
|
-
- you want the agent manager running on your laptop instead of Railway
|
|
91
|
+
Package verification:
|
|
109
92
|
|
|
110
|
-
|
|
93
|
+
- `npm run build:dist`
|
|
94
|
+
- `npm run test:unit`
|
|
95
|
+
- `npm run test:smoke`
|
|
96
|
+
- `npm run release:verify`
|
|
97
|
+
- `npm run verify:local`
|
|
111
98
|
|
|
112
|
-
|
|
113
|
-
cp .env.local-manager-cloudflare.example .env.local-manager-cloudflare
|
|
114
|
-
```
|
|
99
|
+
`npm test` runs both unit tests and the package smoke test. `npm run release:verify` checks local dependency hygiene, rebuilds the distributable package, scans generated output for publish-unsafe source references, runs tests, packs the package, installs it into a temporary project, and verifies the published CLI binary.
|
|
115
100
|
|
|
116
|
-
|
|
101
|
+
## API Composition
|
|
117
102
|
|
|
118
|
-
|
|
119
|
-
- `TREESEED_GATEWAY_BASE_URL`
|
|
120
|
-
- `TREESEED_GATEWAY_BEARER_TOKEN`
|
|
121
|
-
- `CLOUDFLARE_ACCOUNT_ID`
|
|
122
|
-
- `TREESEED_QUEUE_ID`
|
|
103
|
+
Create a backend app with the reusable agent foundation:
|
|
123
104
|
|
|
124
|
-
|
|
105
|
+
```ts
|
|
106
|
+
import { createTreeseedApiApp } from '@treeseed/agent/api';
|
|
125
107
|
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
npm run start:local-manager-cloudflare
|
|
108
|
+
export default createTreeseedApiApp({
|
|
109
|
+
extensions: [
|
|
110
|
+
createMarketApiExtension(),
|
|
111
|
+
],
|
|
112
|
+
});
|
|
132
113
|
```
|
|
133
114
|
|
|
134
|
-
|
|
115
|
+
The agent package owns generic API capabilities such as health, auth/session helpers, task dispatch, queue/capacity endpoints, workday routes, and SDK operation dispatch. Product routes such as market catalog, accounts, billing, invites, and hosted-project management belong in the market app extension.
|
|
116
|
+
|
|
117
|
+
## Processing Host Shape
|
|
118
|
+
|
|
119
|
+
A processing host can run:
|
|
120
|
+
|
|
121
|
+
- API service: `treeseed-agent-api`
|
|
122
|
+
- manager service: `treeseed-agent-service manager`
|
|
123
|
+
- worker runner service: `treeseed-agent-service worker`
|
|
124
|
+
- workday start cron: `treeseed-agent-service workday-start`
|
|
125
|
+
- workday report cron: `treeseed-agent-service workday-report`
|
|
126
|
+
|
|
127
|
+
The processing host registers as a capacity provider and reports health, capabilities, queue metrics, drain state, and workday summaries to the market control plane. Web-only projects should use assigned capacity instead of owning these services.
|
|
128
|
+
|
|
129
|
+
## Environment Registry
|
|
130
|
+
|
|
131
|
+
`src/env.yaml` is the package-owned processing/API env registry. It contains Railway, API, manager, worker, workday, queue, capacity provider, and processing drain entries.
|
|
132
|
+
|
|
133
|
+
Common processing entries include:
|
|
134
|
+
|
|
135
|
+
- `RAILWAY_API_TOKEN`
|
|
136
|
+
- `RAILWAY_TOKEN`
|
|
137
|
+
- `TREESEED_RAILWAY_WORKSPACE`
|
|
138
|
+
- `TREESEED_PROJECT_RUNNER_TOKEN`
|
|
139
|
+
- `TREESEED_AGENT_POOL_MIN_WORKERS`
|
|
140
|
+
- `TREESEED_AGENT_POOL_MAX_WORKERS`
|
|
141
|
+
- `TREESEED_AGENT_POOL_TARGET_QUEUE_DEPTH`
|
|
142
|
+
- `TREESEED_AGENT_POOL_COOLDOWN_SECONDS`
|
|
143
|
+
- `TREESEED_WORKDAY_TIMEZONE`
|
|
144
|
+
- `TREESEED_WORKDAY_WINDOWS_JSON`
|
|
145
|
+
- `TREESEED_WORKDAY_TASK_CREDIT_BUDGET`
|
|
146
|
+
- `TREESEED_MANAGER_MAX_QUEUED_TASKS`
|
|
147
|
+
- `TREESEED_MANAGER_MAX_QUEUED_CREDITS`
|
|
148
|
+
- `TREESEED_MANAGER_PRIORITY_MODELS`
|
|
149
|
+
- `TREESEED_TASK_CREDIT_WEIGHTS_JSON`
|
|
150
|
+
- `TREESEED_WORKER_POOL_SCALER`
|
|
151
|
+
- `TREESEED_RAILWAY_PROJECT_ID`
|
|
152
|
+
- `TREESEED_RAILWAY_ENVIRONMENT_ID`
|
|
153
|
+
- `TREESEED_RAILWAY_WORKER_SERVICE_ID`
|
|
154
|
+
- `TREESEED_API_BASE_URL`
|
|
155
|
+
- `TREESEED_API_AUTH_SECRET`
|
|
156
|
+
- `TREESEED_API_D1_DATABASE_ID`
|
|
157
|
+
- `TREESEED_API_WEB_SERVICE_ID`
|
|
158
|
+
- `TREESEED_API_WEB_SERVICE_SECRET`
|
|
159
|
+
- `TREESEED_API_WEB_ASSERTION_SECRET`
|
|
160
|
+
- `TREESEED_CAPACITY_PROVIDER_ID`
|
|
161
|
+
- `TREESEED_CAPACITY_PROVIDER_TEAM_ID`
|
|
162
|
+
- `TREESEED_CAPACITY_PROVIDER_SERVICE_BASE_URL`
|
|
163
|
+
- `TREESEED_PROCESSING_DRAIN`
|
|
164
|
+
|
|
165
|
+
Provider-neutral shared entries belong in `@treeseed/sdk`. Web/forms/Astro entries belong in `@treeseed/core`. Market product auth, billing, account, hosted-hub, and UI/API entries belong in the root market env overlay.
|
|
135
166
|
|
|
136
|
-
|
|
137
|
-
set -a; source ./.env.local-manager-cloudflare; set +a
|
|
138
|
-
npm run dev:worker
|
|
139
|
-
```
|
|
140
|
-
|
|
141
|
-
Kick off the work day:
|
|
142
|
-
|
|
143
|
-
```bash
|
|
144
|
-
set -a; source ./.env.local-manager-cloudflare; set +a
|
|
145
|
-
npm run dev:workday-start
|
|
146
|
-
```
|
|
167
|
+
## Local Manager With Cloudflare
|
|
147
168
|
|
|
148
|
-
|
|
169
|
+
Use this helper when the web plane is deployed but the processing plane should run locally:
|
|
149
170
|
|
|
150
171
|
```bash
|
|
151
|
-
|
|
152
|
-
npm run
|
|
172
|
+
cp .env.local-manager-cloudflare.example .env.local-manager-cloudflare
|
|
173
|
+
npm run build
|
|
174
|
+
npm run start:local-manager-cloudflare
|
|
153
175
|
```
|
|
154
176
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
Common runtime variables:
|
|
158
|
-
|
|
159
|
-
- `TREESEED_AGENT_REPO_ROOT`
|
|
160
|
-
- `TREESEED_AGENT_D1_DATABASE`
|
|
161
|
-
- `TREESEED_AGENT_D1_PERSIST_TO`
|
|
162
|
-
- `TREESEED_PROJECT_ID`
|
|
163
|
-
- `TREESEED_WORKDAY_CAPACITY_BUDGET`
|
|
164
|
-
- `TREESEED_GATEWAY_BASE_URL`
|
|
165
|
-
- `TREESEED_GATEWAY_BEARER_TOKEN`
|
|
166
|
-
- `TREESEED_MANAGER_BASE_URL`
|
|
167
|
-
- `TREESEED_WORKER_ID`
|
|
168
|
-
- `TREESEED_QUEUE_BATCH_SIZE`
|
|
169
|
-
- `TREESEED_QUEUE_VISIBILITY_TIMEOUT_MS`
|
|
170
|
-
- `TREESEED_TASK_LEASE_SECONDS`
|
|
171
|
-
- `TREESEED_WORKER_POLL_INTERVAL_MS`
|
|
172
|
-
- `CLOUDFLARE_ACCOUNT_ID`
|
|
173
|
-
- `TREESEED_QUEUE_ID`
|
|
174
|
-
- `TREESEED_QUEUE_PULL_TOKEN`
|
|
175
|
-
|
|
176
|
-
## Package Scripts
|
|
177
|
-
|
|
178
|
-
- `npm run setup`: install dependencies with `npm install`
|
|
179
|
-
- `npm run setup:ci`: install dependencies with `npm ci`
|
|
180
|
-
- `npm run build`: build the distributable package
|
|
181
|
-
- `npm run dev:manager`: run the manager directly from source
|
|
182
|
-
- `npm run dev:worker`: run the worker directly from source
|
|
183
|
-
- `npm run dev:workday-start`: run the cron-style start entrypoint directly from source
|
|
184
|
-
- `npm run dev:workday-report`: run the cron-style report entrypoint directly from source
|
|
185
|
-
- `npm run start:manager`: run the built manager
|
|
186
|
-
- `npm run start:worker`: run the built worker
|
|
187
|
-
- `npm run start:workday-start`: run the built workday-start entrypoint
|
|
188
|
-
- `npm run start:workday-report`: run the built workday-report entrypoint
|
|
189
|
-
- `npm run start:local-manager-cloudflare`: load the local-manager env file and start the built manager
|
|
190
|
-
- `npm test`: run the smoke test
|
|
191
|
-
- `npm run release:verify`: verify build, smoke test, and packed-install behavior
|
|
192
|
-
- `npm run release:check-tag -- <tag>`: validate plain semver tags like `0.1.1` against `package.json`
|
|
193
|
-
- `npm run release:publish`: publish to npm
|
|
177
|
+
The purpose-specific env file supplies local processing credentials and Cloudflare queue/D1 pointers without mixing processing-plane secrets into a generic web `.env.local`. Start a local worker, workday start, or workday report in another shell after loading the same env file.
|
|
194
178
|
|
|
195
179
|
## GitHub Actions
|
|
196
180
|
|
|
197
|
-
- `.github/workflows/
|
|
198
|
-
- `.github/workflows/publish.yml`
|
|
181
|
+
- `.github/workflows/verify.yml` runs package verification for pushes and pull requests.
|
|
182
|
+
- `.github/workflows/publish.yml` validates production version tags and publishes the package.
|
|
183
|
+
- `templates/github/deploy-processing.workflow.yml` is the processing-plane workflow template consumed by hosted processing deployments.
|
|
184
|
+
|
|
185
|
+
Web-only hosted projects should dispatch web workflows from `@treeseed/core`/`@treeseed/sdk` templates. Processing deployments should use the agent processing template explicitly.
|
|
@@ -24,7 +24,7 @@ export declare class AgentKernel {
|
|
|
24
24
|
slug: string;
|
|
25
25
|
handler: string;
|
|
26
26
|
enabled: boolean;
|
|
27
|
-
triggers: ("
|
|
27
|
+
triggers: ("startup" | "schedule" | "message" | "follow")[];
|
|
28
28
|
}[];
|
|
29
29
|
diagnostics: import("../spec-types.ts").AgentSpecDiagnostic[];
|
|
30
30
|
}>;
|
package/dist/agents/registry.js
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { mkdtempSync, rmSync } from "node:fs";
|
|
2
|
+
import { existsSync, mkdirSync } from "node:fs";
|
|
3
|
+
import { dirname, extname, resolve } from "node:path";
|
|
3
4
|
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { build } from "esbuild";
|
|
4
6
|
import { getTreeseedAgentProviderSelections } from "@treeseed/sdk/platform/deploy-runtime";
|
|
5
7
|
import { resolveTreeseedTenantRoot } from "@treeseed/sdk/platform/tenant-config";
|
|
6
8
|
import { resolveAgentRuntimeProviders } from "../agent-runtime.js";
|
|
@@ -28,6 +30,58 @@ function getTenantAgentHandlerModulePaths(kind, tenantRoot = resolveTreeseedTena
|
|
|
28
30
|
resolve(tenantRoot, "src/agents", `${kind}.ts`)
|
|
29
31
|
];
|
|
30
32
|
}
|
|
33
|
+
function findNearestTsconfig(startPath) {
|
|
34
|
+
let current = dirname(startPath);
|
|
35
|
+
while (true) {
|
|
36
|
+
const candidate = resolve(current, "tsconfig.json");
|
|
37
|
+
if (existsSync(candidate)) {
|
|
38
|
+
return candidate;
|
|
39
|
+
}
|
|
40
|
+
const parent = resolve(current, "..");
|
|
41
|
+
if (parent === current) {
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
current = parent;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
async function importTenantAgentHandlerModule(modulePath) {
|
|
48
|
+
if (extname(modulePath) !== ".ts") {
|
|
49
|
+
return await import(
|
|
50
|
+
/* @vite-ignore */
|
|
51
|
+
pathToFileURL(modulePath).href
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
const outputParent = resolve(process.cwd(), ".treeseed");
|
|
55
|
+
mkdirSync(outputParent, { recursive: true });
|
|
56
|
+
const outputRoot = mkdtempSync(resolve(outputParent, "agent-handler-"));
|
|
57
|
+
const outputFile = resolve(outputRoot, `${Date.now()}-${Math.random().toString(36).slice(2)}.mjs`);
|
|
58
|
+
const tsconfig = findNearestTsconfig(modulePath);
|
|
59
|
+
try {
|
|
60
|
+
await build({
|
|
61
|
+
entryPoints: [modulePath],
|
|
62
|
+
outfile: outputFile,
|
|
63
|
+
bundle: true,
|
|
64
|
+
format: "esm",
|
|
65
|
+
platform: "node",
|
|
66
|
+
packages: "external",
|
|
67
|
+
logLevel: "silent",
|
|
68
|
+
tsconfig: tsconfig ?? void 0,
|
|
69
|
+
tsconfigRaw: tsconfig ? void 0 : {
|
|
70
|
+
compilerOptions: {
|
|
71
|
+
allowImportingTsExtensions: true,
|
|
72
|
+
module: "ESNext",
|
|
73
|
+
target: "ES2022"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
return await import(
|
|
78
|
+
/* @vite-ignore */
|
|
79
|
+
pathToFileURL(outputFile).href
|
|
80
|
+
);
|
|
81
|
+
} finally {
|
|
82
|
+
rmSync(outputRoot, { recursive: true, force: true });
|
|
83
|
+
}
|
|
84
|
+
}
|
|
31
85
|
async function loadTenantAgentHandlerRegistry(tenantRoot = resolveTreeseedTenantRoot()) {
|
|
32
86
|
const registry = {};
|
|
33
87
|
for (const kind of BUILTIN_HANDLER_KINDS) {
|
|
@@ -37,10 +91,7 @@ async function loadTenantAgentHandlerRegistry(tenantRoot = resolveTreeseedTenant
|
|
|
37
91
|
}
|
|
38
92
|
let moduleExports;
|
|
39
93
|
try {
|
|
40
|
-
moduleExports = await
|
|
41
|
-
/* @vite-ignore */
|
|
42
|
-
pathToFileURL(modulePath).href
|
|
43
|
-
);
|
|
94
|
+
moduleExports = await importTenantAgentHandlerModule(modulePath);
|
|
44
95
|
} catch (error) {
|
|
45
96
|
const reason = error instanceof Error ? error.message : String(error);
|
|
46
97
|
throw new Error(`Failed to import tenant agent handler "${kind}" from ${modulePath}: ${reason}`);
|
package/dist/index.d.ts
CHANGED
|
@@ -3,7 +3,6 @@ export { listTreeseedAgentCommands, renderTreeseedAgentHelp, runTreeseedAgentCli
|
|
|
3
3
|
export { resolveAgentHandler, listRegisteredAgentHandlers } from './agents/registry.ts';
|
|
4
4
|
export { resolveAgentRuntimeProviders } from './agent-runtime.ts';
|
|
5
5
|
export { createTreeseedApiApp, createTreeseedApiRouter, createTreeseedNodeServer, createRailwayTreeseedApiServer, resolveApiConfig, resolveApiRuntimeProviders, } from './api/index.ts';
|
|
6
|
-
export { createManagerApp } from './services/manager.ts';
|
|
7
6
|
export { runScheduledWorkdayManager } from './services/workday-manager.ts';
|
|
8
7
|
export { runWorkerCycle, startWorkerLoop } from './services/worker.ts';
|
|
9
8
|
export { runWorkdayStart } from './services/workday-start.ts';
|
package/dist/index.js
CHANGED
|
@@ -10,7 +10,6 @@ import {
|
|
|
10
10
|
resolveApiConfig,
|
|
11
11
|
resolveApiRuntimeProviders
|
|
12
12
|
} from "./api/index.js";
|
|
13
|
-
import { createManagerApp } from "./services/manager.js";
|
|
14
13
|
import { runScheduledWorkdayManager } from "./services/workday-manager.js";
|
|
15
14
|
import { runWorkerCycle, startWorkerLoop } from "./services/worker.js";
|
|
16
15
|
import { runWorkdayStart } from "./services/workday-start.js";
|
|
@@ -19,7 +18,6 @@ import { parseAgentMessagePayload, AGENT_MESSAGE_TYPES } from "./agents/contract
|
|
|
19
18
|
export {
|
|
20
19
|
AGENT_MESSAGE_TYPES,
|
|
21
20
|
AgentKernel,
|
|
22
|
-
createManagerApp,
|
|
23
21
|
createRailwayTreeseedApiServer,
|
|
24
22
|
createTreeseedApiApp,
|
|
25
23
|
createTreeseedApiRouter,
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
// scripts/publish-package.ts
|
|
2
|
+
import { spawnSync } from "node:child_process";
|
|
3
|
+
import { resolve } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
5
|
+
var packageRoot = resolve(fileURLToPath(new URL("..", import.meta.url)));
|
|
6
|
+
var extraArgs = process.argv.slice(2);
|
|
7
|
+
var tagName = process.env.GITHUB_REF_NAME;
|
|
8
|
+
if (tagName && !/^\d+\.\d+\.\d+$/.test(tagName)) {
|
|
9
|
+
console.error(`Refusing to publish @treeseed/agent from non-stable tag "${tagName}".`);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
var npmArgs = ["publish", ".", "--access", "public"];
|
|
13
|
+
if (process.env.GITHUB_ACTIONS === "true") npmArgs.push("--provenance");
|
|
14
|
+
npmArgs.push(...extraArgs);
|
|
15
|
+
var result = spawnSync("npm", npmArgs, {
|
|
16
|
+
cwd: packageRoot,
|
|
17
|
+
stdio: "inherit",
|
|
18
|
+
env: process.env
|
|
19
|
+
});
|
|
20
|
+
if (result.error) {
|
|
21
|
+
console.error(result.error.message);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
process.exit(result.status ?? 1);
|
|
25
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsicHVibGlzaC1wYWNrYWdlLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBzcGF3blN5bmMgfSBmcm9tICdub2RlOmNoaWxkX3Byb2Nlc3MnO1xuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gJ25vZGU6cGF0aCc7XG5pbXBvcnQgeyBmaWxlVVJMVG9QYXRoIH0gZnJvbSAnbm9kZTp1cmwnO1xuXG5jb25zdCBwYWNrYWdlUm9vdCA9IHJlc29sdmUoZmlsZVVSTFRvUGF0aChuZXcgVVJMKCcuLicsIGltcG9ydC5tZXRhLnVybCkpKTtcbmNvbnN0IGV4dHJhQXJncyA9IHByb2Nlc3MuYXJndi5zbGljZSgyKTtcbmNvbnN0IHRhZ05hbWUgPSBwcm9jZXNzLmVudi5HSVRIVUJfUkVGX05BTUU7XG5cbmlmICh0YWdOYW1lICYmICEvXlxcZCtcXC5cXGQrXFwuXFxkKyQvLnRlc3QodGFnTmFtZSkpIHtcblx0Y29uc29sZS5lcnJvcihgUmVmdXNpbmcgdG8gcHVibGlzaCBAdHJlZXNlZWQvYWdlbnQgZnJvbSBub24tc3RhYmxlIHRhZyBcIiR7dGFnTmFtZX1cIi5gKTtcblx0cHJvY2Vzcy5leGl0KDEpO1xufVxuXG5jb25zdCBucG1BcmdzID0gWydwdWJsaXNoJywgJy4nLCAnLS1hY2Nlc3MnLCAncHVibGljJ107XG5pZiAocHJvY2Vzcy5lbnYuR0lUSFVCX0FDVElPTlMgPT09ICd0cnVlJykgbnBtQXJncy5wdXNoKCctLXByb3ZlbmFuY2UnKTtcbm5wbUFyZ3MucHVzaCguLi5leHRyYUFyZ3MpO1xuXG5jb25zdCByZXN1bHQgPSBzcGF3blN5bmMoJ25wbScsIG5wbUFyZ3MsIHtcblx0Y3dkOiBwYWNrYWdlUm9vdCxcblx0c3RkaW86ICdpbmhlcml0Jyxcblx0ZW52OiBwcm9jZXNzLmVudixcbn0pO1xuXG5pZiAocmVzdWx0LmVycm9yKSB7XG5cdGNvbnNvbGUuZXJyb3IocmVzdWx0LmVycm9yLm1lc3NhZ2UpO1xuXHRwcm9jZXNzLmV4aXQoMSk7XG59XG5cbnByb2Nlc3MuZXhpdChyZXN1bHQuc3RhdHVzID8/IDEpO1xuIl0sCiAgIm1hcHBpbmdzIjogIjtBQUFBLFNBQVMsaUJBQWlCO0FBQzFCLFNBQVMsZUFBZTtBQUN4QixTQUFTLHFCQUFxQjtBQUU5QixJQUFNLGNBQWMsUUFBUSxjQUFjLElBQUksSUFBSSxNQUFNLFlBQVksR0FBRyxDQUFDLENBQUM7QUFDekUsSUFBTSxZQUFZLFFBQVEsS0FBSyxNQUFNLENBQUM7QUFDdEMsSUFBTSxVQUFVLFFBQVEsSUFBSTtBQUU1QixJQUFJLFdBQVcsQ0FBQyxrQkFBa0IsS0FBSyxPQUFPLEdBQUc7QUFDaEQsVUFBUSxNQUFNLDREQUE0RCxPQUFPLElBQUk7QUFDckYsVUFBUSxLQUFLLENBQUM7QUFDZjtBQUVBLElBQU0sVUFBVSxDQUFDLFdBQVcsS0FBSyxZQUFZLFFBQVE7QUFDckQsSUFBSSxRQUFRLElBQUksbUJBQW1CLE9BQVEsU0FBUSxLQUFLLGNBQWM7QUFDdEUsUUFBUSxLQUFLLEdBQUcsU0FBUztBQUV6QixJQUFNLFNBQVMsVUFBVSxPQUFPLFNBQVM7QUFBQSxFQUN4QyxLQUFLO0FBQUEsRUFDTCxPQUFPO0FBQUEsRUFDUCxLQUFLLFFBQVE7QUFDZCxDQUFDO0FBRUQsSUFBSSxPQUFPLE9BQU87QUFDakIsVUFBUSxNQUFNLE9BQU8sTUFBTSxPQUFPO0FBQ2xDLFVBQVEsS0FBSyxDQUFDO0FBQ2Y7QUFFQSxRQUFRLEtBQUssT0FBTyxVQUFVLENBQUM7IiwKICAibmFtZXMiOiBbXQp9Cg==
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
// scripts/build-dist.ts
|
|
2
|
+
import { chmodSync, copyFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { dirname as dirname2, extname, join, relative, resolve as resolve2 } from "node:path";
|
|
4
|
+
import { build } from "esbuild";
|
|
5
|
+
import ts from "typescript";
|
|
6
|
+
|
|
7
|
+
// scripts/package-tools.ts
|
|
8
|
+
import { dirname, resolve } from "node:path";
|
|
9
|
+
import { fileURLToPath } from "node:url";
|
|
10
|
+
var scriptRoot = dirname(fileURLToPath(import.meta.url));
|
|
11
|
+
var packageCandidate = resolve(scriptRoot, "..");
|
|
12
|
+
var packageRoot = packageCandidate.endsWith("/dist") ? resolve(packageCandidate, "..") : packageCandidate;
|
|
13
|
+
|
|
14
|
+
// scripts/build-dist.ts
|
|
15
|
+
var srcRoot = resolve2(packageRoot, "src");
|
|
16
|
+
var scriptsRoot = resolve2(packageRoot, "scripts");
|
|
17
|
+
var templatesRoot = resolve2(packageRoot, "templates");
|
|
18
|
+
var distRoot = resolve2(packageRoot, "dist");
|
|
19
|
+
var JS_SOURCE_EXTENSIONS = /* @__PURE__ */ new Set([".mjs", ".ts"]);
|
|
20
|
+
var COPY_EXTENSIONS = /* @__PURE__ */ new Set([".d.js", ".json", ".jsonc", ".md", ".yaml", ".yml"]);
|
|
21
|
+
function walkFiles(root) {
|
|
22
|
+
const files = [];
|
|
23
|
+
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
24
|
+
const fullPath = join(root, entry.name);
|
|
25
|
+
if (entry.isDirectory()) files.push(...walkFiles(fullPath));
|
|
26
|
+
else files.push(fullPath);
|
|
27
|
+
}
|
|
28
|
+
return files;
|
|
29
|
+
}
|
|
30
|
+
function ensureDir(filePath) {
|
|
31
|
+
mkdirSync(dirname2(filePath), { recursive: true });
|
|
32
|
+
}
|
|
33
|
+
function rewriteRuntimeSpecifiers(contents) {
|
|
34
|
+
return contents.replace(/(['"`])(\.[^'"`\n]+)\.(mjs|ts)\1/g, "$1$2.js$1").replace(/(['"`])\.\.\/src\//g, "$1../");
|
|
35
|
+
}
|
|
36
|
+
async function compileModule(filePath, sourceRoot, outputRoot) {
|
|
37
|
+
const relativePath = relative(sourceRoot, filePath);
|
|
38
|
+
const outputFile = resolve2(outputRoot, relativePath.replace(/\.(mjs|ts)$/u, ".js"));
|
|
39
|
+
ensureDir(outputFile);
|
|
40
|
+
await build({
|
|
41
|
+
entryPoints: [filePath],
|
|
42
|
+
outfile: outputFile,
|
|
43
|
+
platform: "node",
|
|
44
|
+
format: "esm",
|
|
45
|
+
bundle: false,
|
|
46
|
+
logLevel: "silent"
|
|
47
|
+
});
|
|
48
|
+
const builtSource = readFileSync(outputFile, "utf8");
|
|
49
|
+
writeFileSync(outputFile, rewriteRuntimeSpecifiers(builtSource), "utf8");
|
|
50
|
+
}
|
|
51
|
+
function copyAsset(filePath, sourceRoot, outputRoot) {
|
|
52
|
+
const outputFile = resolve2(outputRoot, relative(sourceRoot, filePath));
|
|
53
|
+
ensureDir(outputFile);
|
|
54
|
+
copyFileSync(filePath, outputFile);
|
|
55
|
+
if (outputFile.endsWith(".d.js")) {
|
|
56
|
+
writeFileSync(outputFile, rewriteRuntimeSpecifiers(readFileSync(outputFile, "utf8")), "utf8");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
function transpileScript(filePath) {
|
|
60
|
+
const source = readFileSync(filePath, "utf8");
|
|
61
|
+
const relativePath = relative(scriptsRoot, filePath);
|
|
62
|
+
const outputFile = resolve2(distRoot, "scripts", relativePath.replace(/\.(mjs|ts)$/u, ".js"));
|
|
63
|
+
const transformed = extname(filePath) === ".ts" ? ts.transpileModule(source, {
|
|
64
|
+
compilerOptions: { module: ts.ModuleKind.ESNext, target: ts.ScriptTarget.ES2022 }
|
|
65
|
+
}).outputText : source;
|
|
66
|
+
ensureDir(outputFile);
|
|
67
|
+
writeFileSync(outputFile, rewriteRuntimeSpecifiers(transformed), "utf8");
|
|
68
|
+
chmodSync(outputFile, 493);
|
|
69
|
+
}
|
|
70
|
+
function emitDeclarations() {
|
|
71
|
+
const configPath = ts.findConfigFile(packageRoot, ts.sys.fileExists, "tsconfig.dist.json") ?? ts.findConfigFile(packageRoot, ts.sys.fileExists, "tsconfig.json");
|
|
72
|
+
if (!configPath) throw new Error("Unable to locate a tsconfig for declaration build.");
|
|
73
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
74
|
+
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, packageRoot);
|
|
75
|
+
const program = ts.createProgram({
|
|
76
|
+
rootNames: parsed.fileNames,
|
|
77
|
+
options: { ...parsed.options, declaration: true, emitDeclarationOnly: true, declarationDir: distRoot, noEmit: false }
|
|
78
|
+
});
|
|
79
|
+
const result = program.emit();
|
|
80
|
+
if (result.emitSkipped) throw new Error("Declaration build failed.");
|
|
81
|
+
}
|
|
82
|
+
rmSync(distRoot, { recursive: true, force: true });
|
|
83
|
+
for (const filePath of walkFiles(srcRoot)) {
|
|
84
|
+
const extension = extname(filePath);
|
|
85
|
+
if (JS_SOURCE_EXTENSIONS.has(extension)) await compileModule(filePath, srcRoot, distRoot);
|
|
86
|
+
else if (COPY_EXTENSIONS.has(extension)) copyAsset(filePath, srcRoot, distRoot);
|
|
87
|
+
}
|
|
88
|
+
for (const filePath of walkFiles(scriptsRoot)) {
|
|
89
|
+
const extension = extname(filePath);
|
|
90
|
+
if (JS_SOURCE_EXTENSIONS.has(extension)) transpileScript(filePath);
|
|
91
|
+
}
|
|
92
|
+
emitDeclarations();
|
|
93
|
+
if (existsSync(resolve2(distRoot, "src"))) {
|
|
94
|
+
cpSync(resolve2(distRoot, "src"), distRoot, { recursive: true });
|
|
95
|
+
rmSync(resolve2(distRoot, "src"), { recursive: true, force: true });
|
|
96
|
+
}
|
|
97
|
+
if (existsSync(templatesRoot)) {
|
|
98
|
+
cpSync(templatesRoot, resolve2(distRoot, "templates"), { recursive: true });
|
|
99
|
+
}
|
|
100
|
+
//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiYnVpbGQtZGlzdC50cyIsICJwYWNrYWdlLXRvb2xzLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJpbXBvcnQgeyBjaG1vZFN5bmMsIGNvcHlGaWxlU3luYywgY3BTeW5jLCBleGlzdHNTeW5jLCBta2RpclN5bmMsIHJlYWRkaXJTeW5jLCByZWFkRmlsZVN5bmMsIHJtU3luYywgd3JpdGVGaWxlU3luYyB9IGZyb20gJ25vZGU6ZnMnO1xuaW1wb3J0IHsgZGlybmFtZSwgZXh0bmFtZSwgam9pbiwgcmVsYXRpdmUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgYnVpbGQgfSBmcm9tICdlc2J1aWxkJztcbmltcG9ydCB0cyBmcm9tICd0eXBlc2NyaXB0JztcbmltcG9ydCB7IHBhY2thZ2VSb290IH0gZnJvbSAnLi9wYWNrYWdlLXRvb2xzLnRzJztcblxuY29uc3Qgc3JjUm9vdCA9IHJlc29sdmUocGFja2FnZVJvb3QsICdzcmMnKTtcbmNvbnN0IHNjcmlwdHNSb290ID0gcmVzb2x2ZShwYWNrYWdlUm9vdCwgJ3NjcmlwdHMnKTtcbmNvbnN0IHRlbXBsYXRlc1Jvb3QgPSByZXNvbHZlKHBhY2thZ2VSb290LCAndGVtcGxhdGVzJyk7XG5jb25zdCBkaXN0Um9vdCA9IHJlc29sdmUocGFja2FnZVJvb3QsICdkaXN0Jyk7XG5cbmNvbnN0IEpTX1NPVVJDRV9FWFRFTlNJT05TID0gbmV3IFNldChbJy5tanMnLCAnLnRzJ10pO1xuY29uc3QgQ09QWV9FWFRFTlNJT05TID0gbmV3IFNldChbJy5kLnRzJywgJy5qc29uJywgJy5qc29uYycsICcubWQnLCAnLnlhbWwnLCAnLnltbCddKTtcblxuZnVuY3Rpb24gd2Fsa0ZpbGVzKHJvb3QpIHtcblx0Y29uc3QgZmlsZXMgPSBbXTtcblx0Zm9yIChjb25zdCBlbnRyeSBvZiByZWFkZGlyU3luYyhyb290LCB7IHdpdGhGaWxlVHlwZXM6IHRydWUgfSkpIHtcblx0XHRjb25zdCBmdWxsUGF0aCA9IGpvaW4ocm9vdCwgZW50cnkubmFtZSk7XG5cdFx0aWYgKGVudHJ5LmlzRGlyZWN0b3J5KCkpIGZpbGVzLnB1c2goLi4ud2Fsa0ZpbGVzKGZ1bGxQYXRoKSk7XG5cdFx0ZWxzZSBmaWxlcy5wdXNoKGZ1bGxQYXRoKTtcblx0fVxuXHRyZXR1cm4gZmlsZXM7XG59XG5cbmZ1bmN0aW9uIGVuc3VyZURpcihmaWxlUGF0aCkge1xuXHRta2RpclN5bmMoZGlybmFtZShmaWxlUGF0aCksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuXG5mdW5jdGlvbiByZXdyaXRlUnVudGltZVNwZWNpZmllcnMoY29udGVudHMpIHtcblx0cmV0dXJuIGNvbnRlbnRzXG5cdFx0LnJlcGxhY2UoLyhbJ1wiYF0pKFxcLlteJ1wiYFxcbl0rKVxcLihtanN8dHMpXFwxL2csICckMSQyLmpzJDEnKVxuXHRcdC5yZXBsYWNlKC8oWydcImBdKVxcLlxcLlxcL3NyY1xcLy9nLCAnJDEuLi8nKTtcbn1cblxuYXN5bmMgZnVuY3Rpb24gY29tcGlsZU1vZHVsZShmaWxlUGF0aCwgc291cmNlUm9vdCwgb3V0cHV0Um9vdCkge1xuXHRjb25zdCByZWxhdGl2ZVBhdGggPSByZWxhdGl2ZShzb3VyY2VSb290LCBmaWxlUGF0aCk7XG5cdGNvbnN0IG91dHB1dEZpbGUgPSByZXNvbHZlKG91dHB1dFJvb3QsIHJlbGF0aXZlUGF0aC5yZXBsYWNlKC9cXC4obWpzfHRzKSQvdSwgJy5qcycpKTtcblx0ZW5zdXJlRGlyKG91dHB1dEZpbGUpO1xuXHRhd2FpdCBidWlsZCh7XG5cdFx0ZW50cnlQb2ludHM6IFtmaWxlUGF0aF0sXG5cdFx0b3V0ZmlsZTogb3V0cHV0RmlsZSxcblx0XHRwbGF0Zm9ybTogJ25vZGUnLFxuXHRcdGZvcm1hdDogJ2VzbScsXG5cdFx0YnVuZGxlOiBmYWxzZSxcblx0XHRsb2dMZXZlbDogJ3NpbGVudCcsXG5cdH0pO1xuXHRjb25zdCBidWlsdFNvdXJjZSA9IHJlYWRGaWxlU3luYyhvdXRwdXRGaWxlLCAndXRmOCcpO1xuXHR3cml0ZUZpbGVTeW5jKG91dHB1dEZpbGUsIHJld3JpdGVSdW50aW1lU3BlY2lmaWVycyhidWlsdFNvdXJjZSksICd1dGY4Jyk7XG59XG5cbmZ1bmN0aW9uIGNvcHlBc3NldChmaWxlUGF0aCwgc291cmNlUm9vdCwgb3V0cHV0Um9vdCkge1xuXHRjb25zdCBvdXRwdXRGaWxlID0gcmVzb2x2ZShvdXRwdXRSb290LCByZWxhdGl2ZShzb3VyY2VSb290LCBmaWxlUGF0aCkpO1xuXHRlbnN1cmVEaXIob3V0cHV0RmlsZSk7XG5cdGNvcHlGaWxlU3luYyhmaWxlUGF0aCwgb3V0cHV0RmlsZSk7XG5cdGlmIChvdXRwdXRGaWxlLmVuZHNXaXRoKCcuZC50cycpKSB7XG5cdFx0d3JpdGVGaWxlU3luYyhvdXRwdXRGaWxlLCByZXdyaXRlUnVudGltZVNwZWNpZmllcnMocmVhZEZpbGVTeW5jKG91dHB1dEZpbGUsICd1dGY4JykpLCAndXRmOCcpO1xuXHR9XG59XG5cbmZ1bmN0aW9uIHRyYW5zcGlsZVNjcmlwdChmaWxlUGF0aCkge1xuXHRjb25zdCBzb3VyY2UgPSByZWFkRmlsZVN5bmMoZmlsZVBhdGgsICd1dGY4Jyk7XG5cdGNvbnN0IHJlbGF0aXZlUGF0aCA9IHJlbGF0aXZlKHNjcmlwdHNSb290LCBmaWxlUGF0aCk7XG5cdGNvbnN0IG91dHB1dEZpbGUgPSByZXNvbHZlKGRpc3RSb290LCAnc2NyaXB0cycsIHJlbGF0aXZlUGF0aC5yZXBsYWNlKC9cXC4obWpzfHRzKSQvdSwgJy5qcycpKTtcblx0Y29uc3QgdHJhbnNmb3JtZWQgPSBleHRuYW1lKGZpbGVQYXRoKSA9PT0gJy50cydcblx0XHQ/IHRzLnRyYW5zcGlsZU1vZHVsZShzb3VyY2UsIHtcblx0XHRcdFx0Y29tcGlsZXJPcHRpb25zOiB7IG1vZHVsZTogdHMuTW9kdWxlS2luZC5FU05leHQsIHRhcmdldDogdHMuU2NyaXB0VGFyZ2V0LkVTMjAyMiB9LFxuXHRcdFx0fSkub3V0cHV0VGV4dFxuXHRcdDogc291cmNlO1xuXHRlbnN1cmVEaXIob3V0cHV0RmlsZSk7XG5cdHdyaXRlRmlsZVN5bmMob3V0cHV0RmlsZSwgcmV3cml0ZVJ1bnRpbWVTcGVjaWZpZXJzKHRyYW5zZm9ybWVkKSwgJ3V0ZjgnKTtcblx0Y2htb2RTeW5jKG91dHB1dEZpbGUsIDBvNzU1KTtcbn1cblxuZnVuY3Rpb24gZW1pdERlY2xhcmF0aW9ucygpIHtcblx0Y29uc3QgY29uZmlnUGF0aCA9IHRzLmZpbmRDb25maWdGaWxlKHBhY2thZ2VSb290LCB0cy5zeXMuZmlsZUV4aXN0cywgJ3RzY29uZmlnLmRpc3QuanNvbicpXG5cdFx0Pz8gdHMuZmluZENvbmZpZ0ZpbGUocGFja2FnZVJvb3QsIHRzLnN5cy5maWxlRXhpc3RzLCAndHNjb25maWcuanNvbicpO1xuXHRpZiAoIWNvbmZpZ1BhdGgpIHRocm93IG5ldyBFcnJvcignVW5hYmxlIHRvIGxvY2F0ZSBhIHRzY29uZmlnIGZvciBkZWNsYXJhdGlvbiBidWlsZC4nKTtcblx0Y29uc3QgY29uZmlnRmlsZSA9IHRzLnJlYWRDb25maWdGaWxlKGNvbmZpZ1BhdGgsIHRzLnN5cy5yZWFkRmlsZSk7XG5cdGNvbnN0IHBhcnNlZCA9IHRzLnBhcnNlSnNvbkNvbmZpZ0ZpbGVDb250ZW50KGNvbmZpZ0ZpbGUuY29uZmlnLCB0cy5zeXMsIHBhY2thZ2VSb290KTtcblx0Y29uc3QgcHJvZ3JhbSA9IHRzLmNyZWF0ZVByb2dyYW0oe1xuXHRcdHJvb3ROYW1lczogcGFyc2VkLmZpbGVOYW1lcyxcblx0XHRvcHRpb25zOiB7IC4uLnBhcnNlZC5vcHRpb25zLCBkZWNsYXJhdGlvbjogdHJ1ZSwgZW1pdERlY2xhcmF0aW9uT25seTogdHJ1ZSwgZGVjbGFyYXRpb25EaXI6IGRpc3RSb290LCBub0VtaXQ6IGZhbHNlIH0sXG5cdH0pO1xuXHRjb25zdCByZXN1bHQgPSBwcm9ncmFtLmVtaXQoKTtcblx0aWYgKHJlc3VsdC5lbWl0U2tpcHBlZCkgdGhyb3cgbmV3IEVycm9yKCdEZWNsYXJhdGlvbiBidWlsZCBmYWlsZWQuJyk7XG59XG5cbnJtU3luYyhkaXN0Um9vdCwgeyByZWN1cnNpdmU6IHRydWUsIGZvcmNlOiB0cnVlIH0pO1xuXG5mb3IgKGNvbnN0IGZpbGVQYXRoIG9mIHdhbGtGaWxlcyhzcmNSb290KSkge1xuXHRjb25zdCBleHRlbnNpb24gPSBleHRuYW1lKGZpbGVQYXRoKTtcblx0aWYgKEpTX1NPVVJDRV9FWFRFTlNJT05TLmhhcyhleHRlbnNpb24pKSBhd2FpdCBjb21waWxlTW9kdWxlKGZpbGVQYXRoLCBzcmNSb290LCBkaXN0Um9vdCk7XG5cdGVsc2UgaWYgKENPUFlfRVhURU5TSU9OUy5oYXMoZXh0ZW5zaW9uKSkgY29weUFzc2V0KGZpbGVQYXRoLCBzcmNSb290LCBkaXN0Um9vdCk7XG59XG5cbmZvciAoY29uc3QgZmlsZVBhdGggb2Ygd2Fsa0ZpbGVzKHNjcmlwdHNSb290KSkge1xuXHRjb25zdCBleHRlbnNpb24gPSBleHRuYW1lKGZpbGVQYXRoKTtcblx0aWYgKEpTX1NPVVJDRV9FWFRFTlNJT05TLmhhcyhleHRlbnNpb24pKSB0cmFuc3BpbGVTY3JpcHQoZmlsZVBhdGgpO1xufVxuXG5lbWl0RGVjbGFyYXRpb25zKCk7XG5cbmlmIChleGlzdHNTeW5jKHJlc29sdmUoZGlzdFJvb3QsICdzcmMnKSkpIHtcblx0Y3BTeW5jKHJlc29sdmUoZGlzdFJvb3QsICdzcmMnKSwgZGlzdFJvb3QsIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xuXHRybVN5bmMocmVzb2x2ZShkaXN0Um9vdCwgJ3NyYycpLCB7IHJlY3Vyc2l2ZTogdHJ1ZSwgZm9yY2U6IHRydWUgfSk7XG59XG5cbmlmIChleGlzdHNTeW5jKHRlbXBsYXRlc1Jvb3QpKSB7XG5cdGNwU3luYyh0ZW1wbGF0ZXNSb290LCByZXNvbHZlKGRpc3RSb290LCAndGVtcGxhdGVzJyksIHsgcmVjdXJzaXZlOiB0cnVlIH0pO1xufVxuIiwgImltcG9ydCB7IGRpcm5hbWUsIHJlc29sdmUgfSBmcm9tICdub2RlOnBhdGgnO1xuaW1wb3J0IHsgZmlsZVVSTFRvUGF0aCB9IGZyb20gJ25vZGU6dXJsJztcblxuY29uc3Qgc2NyaXB0Um9vdCA9IGRpcm5hbWUoZmlsZVVSTFRvUGF0aChpbXBvcnQubWV0YS51cmwpKTtcbmNvbnN0IHBhY2thZ2VDYW5kaWRhdGUgPSByZXNvbHZlKHNjcmlwdFJvb3QsICcuLicpO1xuXG5leHBvcnQgY29uc3QgcGFja2FnZVJvb3QgPSBwYWNrYWdlQ2FuZGlkYXRlLmVuZHNXaXRoKCcvZGlzdCcpXG5cdD8gcmVzb2x2ZShwYWNrYWdlQ2FuZGlkYXRlLCAnLi4nKVxuXHQ6IHBhY2thZ2VDYW5kaWRhdGU7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQUEsU0FBUyxXQUFXLGNBQWMsUUFBUSxZQUFZLFdBQVcsYUFBYSxjQUFjLFFBQVEscUJBQXFCO0FBQ3pILFNBQVMsV0FBQUEsVUFBUyxTQUFTLE1BQU0sVUFBVSxXQUFBQyxnQkFBZTtBQUMxRCxTQUFTLGFBQWE7QUFDdEIsT0FBTyxRQUFROzs7QUNIZixTQUFTLFNBQVMsZUFBZTtBQUNqQyxTQUFTLHFCQUFxQjtBQUU5QixJQUFNLGFBQWEsUUFBUSxjQUFjLFlBQVksR0FBRyxDQUFDO0FBQ3pELElBQU0sbUJBQW1CLFFBQVEsWUFBWSxJQUFJO0FBRTFDLElBQU0sY0FBYyxpQkFBaUIsU0FBUyxPQUFPLElBQ3pELFFBQVEsa0JBQWtCLElBQUksSUFDOUI7OztBREZILElBQU0sVUFBVUMsU0FBUSxhQUFhLEtBQUs7QUFDMUMsSUFBTSxjQUFjQSxTQUFRLGFBQWEsU0FBUztBQUNsRCxJQUFNLGdCQUFnQkEsU0FBUSxhQUFhLFdBQVc7QUFDdEQsSUFBTSxXQUFXQSxTQUFRLGFBQWEsTUFBTTtBQUU1QyxJQUFNLHVCQUF1QixvQkFBSSxJQUFJLENBQUMsUUFBUSxLQUFLLENBQUM7QUFDcEQsSUFBTSxrQkFBa0Isb0JBQUksSUFBSSxDQUFDLFNBQVMsU0FBUyxVQUFVLE9BQU8sU0FBUyxNQUFNLENBQUM7QUFFcEYsU0FBUyxVQUFVLE1BQU07QUFDeEIsUUFBTSxRQUFRLENBQUM7QUFDZixhQUFXLFNBQVMsWUFBWSxNQUFNLEVBQUUsZUFBZSxLQUFLLENBQUMsR0FBRztBQUMvRCxVQUFNLFdBQVcsS0FBSyxNQUFNLE1BQU0sSUFBSTtBQUN0QyxRQUFJLE1BQU0sWUFBWSxFQUFHLE9BQU0sS0FBSyxHQUFHLFVBQVUsUUFBUSxDQUFDO0FBQUEsUUFDckQsT0FBTSxLQUFLLFFBQVE7QUFBQSxFQUN6QjtBQUNBLFNBQU87QUFDUjtBQUVBLFNBQVMsVUFBVSxVQUFVO0FBQzVCLFlBQVVDLFNBQVEsUUFBUSxHQUFHLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDakQ7QUFFQSxTQUFTLHlCQUF5QixVQUFVO0FBQzNDLFNBQU8sU0FDTCxRQUFRLHFDQUFxQyxXQUFXLEVBQ3hELFFBQVEsdUJBQXVCLE9BQU87QUFDekM7QUFFQSxlQUFlLGNBQWMsVUFBVSxZQUFZLFlBQVk7QUFDOUQsUUFBTSxlQUFlLFNBQVMsWUFBWSxRQUFRO0FBQ2xELFFBQU0sYUFBYUQsU0FBUSxZQUFZLGFBQWEsUUFBUSxnQkFBZ0IsS0FBSyxDQUFDO0FBQ2xGLFlBQVUsVUFBVTtBQUNwQixRQUFNLE1BQU07QUFBQSxJQUNYLGFBQWEsQ0FBQyxRQUFRO0FBQUEsSUFDdEIsU0FBUztBQUFBLElBQ1QsVUFBVTtBQUFBLElBQ1YsUUFBUTtBQUFBLElBQ1IsUUFBUTtBQUFBLElBQ1IsVUFBVTtBQUFBLEVBQ1gsQ0FBQztBQUNELFFBQU0sY0FBYyxhQUFhLFlBQVksTUFBTTtBQUNuRCxnQkFBYyxZQUFZLHlCQUF5QixXQUFXLEdBQUcsTUFBTTtBQUN4RTtBQUVBLFNBQVMsVUFBVSxVQUFVLFlBQVksWUFBWTtBQUNwRCxRQUFNLGFBQWFBLFNBQVEsWUFBWSxTQUFTLFlBQVksUUFBUSxDQUFDO0FBQ3JFLFlBQVUsVUFBVTtBQUNwQixlQUFhLFVBQVUsVUFBVTtBQUNqQyxNQUFJLFdBQVcsU0FBUyxPQUFPLEdBQUc7QUFDakMsa0JBQWMsWUFBWSx5QkFBeUIsYUFBYSxZQUFZLE1BQU0sQ0FBQyxHQUFHLE1BQU07QUFBQSxFQUM3RjtBQUNEO0FBRUEsU0FBUyxnQkFBZ0IsVUFBVTtBQUNsQyxRQUFNLFNBQVMsYUFBYSxVQUFVLE1BQU07QUFDNUMsUUFBTSxlQUFlLFNBQVMsYUFBYSxRQUFRO0FBQ25ELFFBQU0sYUFBYUEsU0FBUSxVQUFVLFdBQVcsYUFBYSxRQUFRLGdCQUFnQixLQUFLLENBQUM7QUFDM0YsUUFBTSxjQUFjLFFBQVEsUUFBUSxNQUFNLFFBQ3ZDLEdBQUcsZ0JBQWdCLFFBQVE7QUFBQSxJQUMzQixpQkFBaUIsRUFBRSxRQUFRLEdBQUcsV0FBVyxRQUFRLFFBQVEsR0FBRyxhQUFhLE9BQU87QUFBQSxFQUNqRixDQUFDLEVBQUUsYUFDRjtBQUNILFlBQVUsVUFBVTtBQUNwQixnQkFBYyxZQUFZLHlCQUF5QixXQUFXLEdBQUcsTUFBTTtBQUN2RSxZQUFVLFlBQVksR0FBSztBQUM1QjtBQUVBLFNBQVMsbUJBQW1CO0FBQzNCLFFBQU0sYUFBYSxHQUFHLGVBQWUsYUFBYSxHQUFHLElBQUksWUFBWSxvQkFBb0IsS0FDckYsR0FBRyxlQUFlLGFBQWEsR0FBRyxJQUFJLFlBQVksZUFBZTtBQUNyRSxNQUFJLENBQUMsV0FBWSxPQUFNLElBQUksTUFBTSxvREFBb0Q7QUFDckYsUUFBTSxhQUFhLEdBQUcsZUFBZSxZQUFZLEdBQUcsSUFBSSxRQUFRO0FBQ2hFLFFBQU0sU0FBUyxHQUFHLDJCQUEyQixXQUFXLFFBQVEsR0FBRyxLQUFLLFdBQVc7QUFDbkYsUUFBTSxVQUFVLEdBQUcsY0FBYztBQUFBLElBQ2hDLFdBQVcsT0FBTztBQUFBLElBQ2xCLFNBQVMsRUFBRSxHQUFHLE9BQU8sU0FBUyxhQUFhLE1BQU0scUJBQXFCLE1BQU0sZ0JBQWdCLFVBQVUsUUFBUSxNQUFNO0FBQUEsRUFDckgsQ0FBQztBQUNELFFBQU0sU0FBUyxRQUFRLEtBQUs7QUFDNUIsTUFBSSxPQUFPLFlBQWEsT0FBTSxJQUFJLE1BQU0sMkJBQTJCO0FBQ3BFO0FBRUEsT0FBTyxVQUFVLEVBQUUsV0FBVyxNQUFNLE9BQU8sS0FBSyxDQUFDO0FBRWpELFdBQVcsWUFBWSxVQUFVLE9BQU8sR0FBRztBQUMxQyxRQUFNLFlBQVksUUFBUSxRQUFRO0FBQ2xDLE1BQUkscUJBQXFCLElBQUksU0FBUyxFQUFHLE9BQU0sY0FBYyxVQUFVLFNBQVMsUUFBUTtBQUFBLFdBQy9FLGdCQUFnQixJQUFJLFNBQVMsRUFBRyxXQUFVLFVBQVUsU0FBUyxRQUFRO0FBQy9FO0FBRUEsV0FBVyxZQUFZLFVBQVUsV0FBVyxHQUFHO0FBQzlDLFFBQU0sWUFBWSxRQUFRLFFBQVE7QUFDbEMsTUFBSSxxQkFBcUIsSUFBSSxTQUFTLEVBQUcsaUJBQWdCLFFBQVE7QUFDbEU7QUFFQSxpQkFBaUI7QUFFakIsSUFBSSxXQUFXQSxTQUFRLFVBQVUsS0FBSyxDQUFDLEdBQUc7QUFDekMsU0FBT0EsU0FBUSxVQUFVLEtBQUssR0FBRyxVQUFVLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDOUQsU0FBT0EsU0FBUSxVQUFVLEtBQUssR0FBRyxFQUFFLFdBQVcsTUFBTSxPQUFPLEtBQUssQ0FBQztBQUNsRTtBQUVBLElBQUksV0FBVyxhQUFhLEdBQUc7QUFDOUIsU0FBTyxlQUFlQSxTQUFRLFVBQVUsV0FBVyxHQUFHLEVBQUUsV0FBVyxLQUFLLENBQUM7QUFDMUU7IiwKICAibmFtZXMiOiBbImRpcm5hbWUiLCAicmVzb2x2ZSIsICJyZXNvbHZlIiwgImRpcm5hbWUiXQp9Cg==
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { copyFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync
|
|
1
|
+
import { chmodSync, copyFileSync, cpSync, existsSync, mkdirSync, readdirSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, extname, join, relative, resolve } from 'node:path';
|
|
3
3
|
import { build } from 'esbuild';
|
|
4
4
|
import ts from 'typescript';
|
|
@@ -7,7 +7,8 @@ const srcRoot = resolve(packageRoot, 'src');
|
|
|
7
7
|
const scriptsRoot = resolve(packageRoot, 'scripts');
|
|
8
8
|
const templatesRoot = resolve(packageRoot, 'templates');
|
|
9
9
|
const distRoot = resolve(packageRoot, 'dist');
|
|
10
|
-
const
|
|
10
|
+
const JS_SOURCE_EXTENSIONS = new Set(['.mjs', '.ts']);
|
|
11
|
+
const COPY_EXTENSIONS = new Set(['.d.js', '.json', '.jsonc', '.md', '.yaml', '.yml']);
|
|
11
12
|
function walkFiles(root) {
|
|
12
13
|
const files = [];
|
|
13
14
|
for (const entry of readdirSync(root, { withFileTypes: true })) {
|
|
@@ -64,9 +65,10 @@ function transpileScript(filePath) {
|
|
|
64
65
|
chmodSync(outputFile, 0o755);
|
|
65
66
|
}
|
|
66
67
|
function emitDeclarations() {
|
|
67
|
-
const configPath = ts.findConfigFile(packageRoot, ts.sys.fileExists, 'tsconfig.json')
|
|
68
|
+
const configPath = ts.findConfigFile(packageRoot, ts.sys.fileExists, 'tsconfig.dist.json')
|
|
69
|
+
?? ts.findConfigFile(packageRoot, ts.sys.fileExists, 'tsconfig.json');
|
|
68
70
|
if (!configPath)
|
|
69
|
-
throw new Error('Unable to locate tsconfig
|
|
71
|
+
throw new Error('Unable to locate a tsconfig for declaration build.');
|
|
70
72
|
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
71
73
|
const parsed = ts.parseJsonConfigFileContent(configFile.config, ts.sys, packageRoot);
|
|
72
74
|
const program = ts.createProgram({
|
|
@@ -80,14 +82,14 @@ function emitDeclarations() {
|
|
|
80
82
|
rmSync(distRoot, { recursive: true, force: true });
|
|
81
83
|
for (const filePath of walkFiles(srcRoot)) {
|
|
82
84
|
const extension = extname(filePath);
|
|
83
|
-
if (extension
|
|
85
|
+
if (JS_SOURCE_EXTENSIONS.has(extension))
|
|
84
86
|
await compileModule(filePath, srcRoot, distRoot);
|
|
85
87
|
else if (COPY_EXTENSIONS.has(extension))
|
|
86
88
|
copyAsset(filePath, srcRoot, distRoot);
|
|
87
89
|
}
|
|
88
90
|
for (const filePath of walkFiles(scriptsRoot)) {
|
|
89
91
|
const extension = extname(filePath);
|
|
90
|
-
if (
|
|
92
|
+
if (JS_SOURCE_EXTENSIONS.has(extension))
|
|
91
93
|
transpileScript(filePath);
|
|
92
94
|
}
|
|
93
95
|
emitDeclarations();
|
|
@@ -95,12 +97,6 @@ if (existsSync(resolve(distRoot, 'src'))) {
|
|
|
95
97
|
cpSync(resolve(distRoot, 'src'), distRoot, { recursive: true });
|
|
96
98
|
rmSync(resolve(distRoot, 'src'), { recursive: true, force: true });
|
|
97
99
|
}
|
|
98
|
-
if (existsSync(resolve(packageRoot, 'README.md'))) {
|
|
99
|
-
copyFileSync(resolve(packageRoot, 'README.md'), resolve(distRoot, '..', 'README.md'));
|
|
100
|
-
}
|
|
101
|
-
if (existsSync(resolve(packageRoot, 'Dockerfile'))) {
|
|
102
|
-
copyFileSync(resolve(packageRoot, 'Dockerfile'), resolve(distRoot, '..', 'Dockerfile'));
|
|
103
|
-
}
|
|
104
100
|
if (existsSync(templatesRoot)) {
|
|
105
101
|
cpSync(templatesRoot, resolve(distRoot, 'templates'), { recursive: true });
|
|
106
102
|
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
if (process.env.TREESEED_SKIP_PACKAGE_PREPARE === '1') {
|
|
6
|
+
process.exit(0);
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
const result = spawnSync('npm', ['run', 'build:dist'], {
|
|
10
|
+
stdio: 'inherit',
|
|
11
|
+
shell: process.platform === 'win32',
|
|
12
|
+
});
|
|
13
|
+
|
|
14
|
+
process.exit(result.status ?? 1);
|
|
@@ -55,6 +55,32 @@ function scanDirectory(root) {
|
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
57
|
}
|
|
58
|
+
function assertNoLocalDependencyLinks() {
|
|
59
|
+
const packageJson = JSON.parse(readFileSync(resolve(packageRoot, 'package.json'), 'utf8'));
|
|
60
|
+
for (const sectionName of ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies']) {
|
|
61
|
+
for (const [dependencyName, version] of Object.entries(packageJson[sectionName] ?? {})) {
|
|
62
|
+
if (version.startsWith('workspace:') || version.startsWith('file:')) {
|
|
63
|
+
throw new Error(`package.json ${sectionName}.${dependencyName} must not use local dependency specifiers: ${version}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const lockfile = JSON.parse(readFileSync(resolve(packageRoot, 'package-lock.json'), 'utf8'));
|
|
68
|
+
for (const [entryKey, entryValue] of Object.entries(lockfile.packages ?? {})) {
|
|
69
|
+
if (entryKey.startsWith('../') || entryKey.includes('/../')) {
|
|
70
|
+
throw new Error(`package-lock.json contains forbidden local package entry: ${entryKey}`);
|
|
71
|
+
}
|
|
72
|
+
if (entryValue.link) {
|
|
73
|
+
throw new Error(`package-lock.json contains forbidden linked dependency entry: ${entryKey}`);
|
|
74
|
+
}
|
|
75
|
+
const resolved = entryValue.resolved ?? '';
|
|
76
|
+
if (resolved.startsWith('../')
|
|
77
|
+
|| resolved.startsWith('./')
|
|
78
|
+
|| resolved.startsWith('file:')
|
|
79
|
+
|| resolved.startsWith('workspace:')) {
|
|
80
|
+
throw new Error(`package-lock.json contains forbidden local resolution for ${entryKey}: ${resolved}`);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
58
84
|
function resolveNodeModulesRoot() {
|
|
59
85
|
let lastCandidate = null;
|
|
60
86
|
let current = packageRoot;
|
|
@@ -131,8 +157,10 @@ function installDependencyPackage(root, extractRoot, tempRoot, folderName, fallb
|
|
|
131
157
|
const tarballPath = pack(root, fallbackName);
|
|
132
158
|
installPackagedPackage(extractRoot, tempRoot, tarballPath, folderName);
|
|
133
159
|
}
|
|
160
|
+
assertNoLocalDependencyLinks();
|
|
134
161
|
run('npm', ['run', 'lint']);
|
|
135
162
|
scanDirectory(resolve(packageRoot, 'dist'));
|
|
163
|
+
run('npm', ['run', 'test:unit']);
|
|
136
164
|
run('npm', ['run', 'test:smoke']);
|
|
137
165
|
const stageRoot = mkdtempSync(join(tmpdir(), 'treeseed-agent-release-'));
|
|
138
166
|
const extractRoot = resolve(stageRoot, 'extract');
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { build } from 'esbuild';
|
|
4
|
+
import { readFileSync, rmSync, writeFileSync } from 'node:fs';
|
|
5
|
+
import { dirname, resolve } from 'node:path';
|
|
6
|
+
import { pathToFileURL } from 'node:url';
|
|
7
|
+
|
|
8
|
+
const [, , entryArg, ...scriptArgs] = process.argv;
|
|
9
|
+
|
|
10
|
+
if (!entryArg) {
|
|
11
|
+
console.error('Usage: node ./scripts/run-ts.mjs <entry.ts> [...args]');
|
|
12
|
+
process.exit(1);
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
const cwd = process.cwd();
|
|
16
|
+
const entryPath = resolve(cwd, entryArg);
|
|
17
|
+
const outfile = resolve(
|
|
18
|
+
dirname(entryPath),
|
|
19
|
+
`.ts-run-${Date.now()}-${Math.random().toString(36).slice(2)}.js`,
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
await build({
|
|
24
|
+
entryPoints: [entryPath],
|
|
25
|
+
outfile,
|
|
26
|
+
bundle: true,
|
|
27
|
+
format: 'esm',
|
|
28
|
+
platform: 'node',
|
|
29
|
+
packages: 'external',
|
|
30
|
+
sourcemap: 'inline',
|
|
31
|
+
logLevel: 'silent',
|
|
32
|
+
});
|
|
33
|
+
|
|
34
|
+
const builtSource = readFileSync(outfile, 'utf8');
|
|
35
|
+
writeFileSync(
|
|
36
|
+
outfile,
|
|
37
|
+
builtSource.replace(/(['"`])(\.[^'"`\n]+)\.ts\1/g, '$1$2.js$1'),
|
|
38
|
+
'utf8',
|
|
39
|
+
);
|
|
40
|
+
|
|
41
|
+
process.argv = [process.argv[0] ?? 'node', entryPath, ...scriptArgs];
|
|
42
|
+
await import(pathToFileURL(outfile).href);
|
|
43
|
+
} finally {
|
|
44
|
+
rmSync(outfile, { force: true });
|
|
45
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import { spawnSync } from 'node:child_process';
|
|
4
|
+
|
|
5
|
+
function runDirectVerify() {
|
|
6
|
+
const result = spawnSync('npm', ['run', 'verify:direct'], {
|
|
7
|
+
cwd: process.cwd(),
|
|
8
|
+
env: process.env,
|
|
9
|
+
stdio: 'inherit',
|
|
10
|
+
});
|
|
11
|
+
process.exit(result.status ?? 1);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const entrypointCheckOnly = process.env.TREESEED_VERIFY_ENTRYPOINT_CHECK === 'true';
|
|
15
|
+
|
|
16
|
+
try {
|
|
17
|
+
await import('@treeseed/sdk/scripts/verify-driver');
|
|
18
|
+
if (entrypointCheckOnly) {
|
|
19
|
+
process.exit(0);
|
|
20
|
+
}
|
|
21
|
+
} catch (error) {
|
|
22
|
+
if (error && typeof error === 'object' && 'code' in error && error.code === 'ERR_MODULE_NOT_FOUND') {
|
|
23
|
+
if (entrypointCheckOnly) {
|
|
24
|
+
process.stderr.write('Treeseed agent verify: @treeseed/sdk is required for verify entrypoint resolution.\n');
|
|
25
|
+
process.exit(1);
|
|
26
|
+
}
|
|
27
|
+
if (process.env.TREESEED_VERIFY_DRIVER === 'act') {
|
|
28
|
+
process.stderr.write('Treeseed agent verify: `act` mode requires @treeseed/sdk to be installed.\n');
|
|
29
|
+
process.exit(1);
|
|
30
|
+
}
|
|
31
|
+
runDirectVerify();
|
|
32
|
+
}
|
|
33
|
+
throw error;
|
|
34
|
+
}
|
package/dist/services/common.js
CHANGED
|
@@ -177,7 +177,7 @@ function resolveManagerConfig() {
|
|
|
177
177
|
host: process.env.HOST?.trim() || "0.0.0.0",
|
|
178
178
|
port: integerFromEnv("PORT", 3100),
|
|
179
179
|
projectId: process.env.TREESEED_PROJECT_ID?.trim() || "treeseed-market",
|
|
180
|
-
defaultCapacityBudget: integerFromEnv("
|
|
180
|
+
defaultCapacityBudget: integerFromEnv("TREESEED_WORKDAY_TASK_CREDIT_BUDGET", 100)
|
|
181
181
|
};
|
|
182
182
|
}
|
|
183
183
|
function resolveWorkerConfig() {
|
|
@@ -48,7 +48,7 @@ export declare function runManagerAction(options?: {
|
|
|
48
48
|
mode: "reconcile";
|
|
49
49
|
managerId: string;
|
|
50
50
|
projectId: string;
|
|
51
|
-
environment: "local" | "
|
|
51
|
+
environment: "local" | "prod" | "staging";
|
|
52
52
|
insideWorkWindow: boolean;
|
|
53
53
|
workPolicy: WorkdayPolicy;
|
|
54
54
|
workDay: null;
|
|
@@ -71,7 +71,7 @@ export declare function runManagerAction(options?: {
|
|
|
71
71
|
mode: "reconcile";
|
|
72
72
|
managerId: string;
|
|
73
73
|
projectId: string;
|
|
74
|
-
environment: "local" | "
|
|
74
|
+
environment: "local" | "prod" | "staging";
|
|
75
75
|
insideWorkWindow: boolean;
|
|
76
76
|
workPolicy: WorkdayPolicy;
|
|
77
77
|
workDay: Record<string, unknown>;
|
|
@@ -141,7 +141,7 @@ export declare function runManagerAction(options?: {
|
|
|
141
141
|
grantCount: number;
|
|
142
142
|
} | null;
|
|
143
143
|
projectId: string;
|
|
144
|
-
environment: "local" | "
|
|
144
|
+
environment: "local" | "prod" | "staging";
|
|
145
145
|
workDayId: string;
|
|
146
146
|
state: string;
|
|
147
147
|
totalTasks: number;
|
|
@@ -228,7 +228,7 @@ export declare function runManagerAction(options?: {
|
|
|
228
228
|
grantCount: number;
|
|
229
229
|
} | null;
|
|
230
230
|
projectId: string;
|
|
231
|
-
environment: "local" | "
|
|
231
|
+
environment: "local" | "prod" | "staging";
|
|
232
232
|
workDayId: string;
|
|
233
233
|
state: string;
|
|
234
234
|
totalTasks: number;
|
|
@@ -289,7 +289,7 @@ export declare function runManagerCycle(options?: {
|
|
|
289
289
|
mode: "reconcile";
|
|
290
290
|
managerId: string;
|
|
291
291
|
projectId: string;
|
|
292
|
-
environment: "local" | "
|
|
292
|
+
environment: "local" | "prod" | "staging";
|
|
293
293
|
insideWorkWindow: boolean;
|
|
294
294
|
workPolicy: WorkdayPolicy;
|
|
295
295
|
workDay: null;
|
|
@@ -312,7 +312,7 @@ export declare function runManagerCycle(options?: {
|
|
|
312
312
|
mode: "reconcile";
|
|
313
313
|
managerId: string;
|
|
314
314
|
projectId: string;
|
|
315
|
-
environment: "local" | "
|
|
315
|
+
environment: "local" | "prod" | "staging";
|
|
316
316
|
insideWorkWindow: boolean;
|
|
317
317
|
workPolicy: WorkdayPolicy;
|
|
318
318
|
workDay: Record<string, unknown>;
|
package/dist/services/manager.js
CHANGED
|
@@ -371,10 +371,7 @@ function resolveManagerServiceConfig() {
|
|
|
371
371
|
const environment = envValue("TREESEED_DEPLOY_ENVIRONMENT") || (process.env.NODE_ENV === "production" ? "prod" : "local");
|
|
372
372
|
const projectId = envValue("TREESEED_PROJECT_ID") || shared.projectId;
|
|
373
373
|
const teamId = envValue("TREESEED_HOSTING_TEAM_ID") || envValue("TREESEED_CONTENT_DEFAULT_TEAM_ID") || projectId;
|
|
374
|
-
const dailyTaskCreditBudget = integerFromEnv(
|
|
375
|
-
"TREESEED_WORKDAY_TASK_CREDIT_BUDGET",
|
|
376
|
-
integerFromEnv("TREESEED_WORKDAY_CAPACITY_BUDGET", shared.defaultCapacityBudget)
|
|
377
|
-
);
|
|
374
|
+
const dailyTaskCreditBudget = integerFromEnv("TREESEED_WORKDAY_TASK_CREDIT_BUDGET", shared.defaultCapacityBudget);
|
|
378
375
|
const maxQueuedTasks = integerFromEnv("TREESEED_MANAGER_MAX_QUEUED_TASKS", Math.max(1, Math.min(20, dailyTaskCreditBudget)));
|
|
379
376
|
const maxQueuedCredits = integerFromEnv("TREESEED_MANAGER_MAX_QUEUED_CREDITS", Math.max(1, Math.min(dailyTaskCreditBudget, maxQueuedTasks * 4)));
|
|
380
377
|
return {
|
|
@@ -23,7 +23,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
23
23
|
mode: "reconcile";
|
|
24
24
|
managerId: string;
|
|
25
25
|
projectId: string;
|
|
26
|
-
environment: "local" | "
|
|
26
|
+
environment: "local" | "prod" | "staging";
|
|
27
27
|
insideWorkWindow: boolean;
|
|
28
28
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
29
29
|
workDay: null;
|
|
@@ -46,7 +46,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
46
46
|
mode: "reconcile";
|
|
47
47
|
managerId: string;
|
|
48
48
|
projectId: string;
|
|
49
|
-
environment: "local" | "
|
|
49
|
+
environment: "local" | "prod" | "staging";
|
|
50
50
|
insideWorkWindow: boolean;
|
|
51
51
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
52
52
|
workDay: Record<string, unknown>;
|
|
@@ -69,7 +69,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
69
69
|
mode: "reconcile";
|
|
70
70
|
managerId: string;
|
|
71
71
|
projectId: string;
|
|
72
|
-
environment: "local" | "
|
|
72
|
+
environment: "local" | "prod" | "staging";
|
|
73
73
|
insideWorkWindow: boolean;
|
|
74
74
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
75
75
|
workDay: null;
|
|
@@ -92,7 +92,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
92
92
|
mode: "reconcile";
|
|
93
93
|
managerId: string;
|
|
94
94
|
projectId: string;
|
|
95
|
-
environment: "local" | "
|
|
95
|
+
environment: "local" | "prod" | "staging";
|
|
96
96
|
insideWorkWindow: boolean;
|
|
97
97
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
98
98
|
workDay: Record<string, unknown>;
|
|
@@ -111,7 +111,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
111
111
|
mode: "reconcile";
|
|
112
112
|
managerId: string;
|
|
113
113
|
projectId: string;
|
|
114
|
-
environment: "local" | "
|
|
114
|
+
environment: "local" | "prod" | "staging";
|
|
115
115
|
insideWorkWindow: boolean;
|
|
116
116
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
117
117
|
workDay: null;
|
|
@@ -134,7 +134,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
134
134
|
mode: "reconcile";
|
|
135
135
|
managerId: string;
|
|
136
136
|
projectId: string;
|
|
137
|
-
environment: "local" | "
|
|
137
|
+
environment: "local" | "prod" | "staging";
|
|
138
138
|
insideWorkWindow: boolean;
|
|
139
139
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
140
140
|
workDay: Record<string, unknown>;
|
|
@@ -153,7 +153,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
153
153
|
mode: "reconcile";
|
|
154
154
|
managerId: string;
|
|
155
155
|
projectId: string;
|
|
156
|
-
environment: "local" | "
|
|
156
|
+
environment: "local" | "prod" | "staging";
|
|
157
157
|
insideWorkWindow: boolean;
|
|
158
158
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
159
159
|
workDay: null;
|
|
@@ -176,7 +176,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
176
176
|
mode: "reconcile";
|
|
177
177
|
managerId: string;
|
|
178
178
|
projectId: string;
|
|
179
|
-
environment: "local" | "
|
|
179
|
+
environment: "local" | "prod" | "staging";
|
|
180
180
|
insideWorkWindow: boolean;
|
|
181
181
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
182
182
|
workDay: Record<string, unknown>;
|
|
@@ -248,7 +248,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
248
248
|
grantCount: number;
|
|
249
249
|
} | null;
|
|
250
250
|
projectId: string;
|
|
251
|
-
environment: "local" | "
|
|
251
|
+
environment: "local" | "prod" | "staging";
|
|
252
252
|
workDayId: string;
|
|
253
253
|
state: string;
|
|
254
254
|
totalTasks: number;
|
|
@@ -335,7 +335,7 @@ export declare function runScheduledWorkdayManager(options?: {
|
|
|
335
335
|
grantCount: number;
|
|
336
336
|
} | null;
|
|
337
337
|
projectId: string;
|
|
338
|
-
environment: "local" | "
|
|
338
|
+
environment: "local" | "prod" | "staging";
|
|
339
339
|
workDayId: string;
|
|
340
340
|
state: string;
|
|
341
341
|
totalTasks: number;
|
|
@@ -4,7 +4,7 @@ export declare function runWorkdayReport(): Promise<{
|
|
|
4
4
|
mode: "reconcile";
|
|
5
5
|
managerId: string;
|
|
6
6
|
projectId: string;
|
|
7
|
-
environment: "local" | "
|
|
7
|
+
environment: "local" | "prod" | "staging";
|
|
8
8
|
insideWorkWindow: boolean;
|
|
9
9
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
10
10
|
workDay: null;
|
|
@@ -27,7 +27,7 @@ export declare function runWorkdayReport(): Promise<{
|
|
|
27
27
|
mode: "reconcile";
|
|
28
28
|
managerId: string;
|
|
29
29
|
projectId: string;
|
|
30
|
-
environment: "local" | "
|
|
30
|
+
environment: "local" | "prod" | "staging";
|
|
31
31
|
insideWorkWindow: boolean;
|
|
32
32
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
33
33
|
workDay: Record<string, unknown>;
|
|
@@ -99,7 +99,7 @@ export declare function runWorkdayReport(): Promise<{
|
|
|
99
99
|
grantCount: number;
|
|
100
100
|
} | null;
|
|
101
101
|
projectId: string;
|
|
102
|
-
environment: "local" | "
|
|
102
|
+
environment: "local" | "prod" | "staging";
|
|
103
103
|
workDayId: string;
|
|
104
104
|
state: string;
|
|
105
105
|
totalTasks: number;
|
|
@@ -186,7 +186,7 @@ export declare function runWorkdayReport(): Promise<{
|
|
|
186
186
|
grantCount: number;
|
|
187
187
|
} | null;
|
|
188
188
|
projectId: string;
|
|
189
|
-
environment: "local" | "
|
|
189
|
+
environment: "local" | "prod" | "staging";
|
|
190
190
|
workDayId: string;
|
|
191
191
|
state: string;
|
|
192
192
|
totalTasks: number;
|
|
@@ -4,7 +4,7 @@ export declare function runWorkdayStart(): Promise<{
|
|
|
4
4
|
mode: "reconcile";
|
|
5
5
|
managerId: string;
|
|
6
6
|
projectId: string;
|
|
7
|
-
environment: "local" | "
|
|
7
|
+
environment: "local" | "prod" | "staging";
|
|
8
8
|
insideWorkWindow: boolean;
|
|
9
9
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
10
10
|
workDay: null;
|
|
@@ -27,7 +27,7 @@ export declare function runWorkdayStart(): Promise<{
|
|
|
27
27
|
mode: "reconcile";
|
|
28
28
|
managerId: string;
|
|
29
29
|
projectId: string;
|
|
30
|
-
environment: "local" | "
|
|
30
|
+
environment: "local" | "prod" | "staging";
|
|
31
31
|
insideWorkWindow: boolean;
|
|
32
32
|
workPolicy: import("@treeseed/sdk").WorkdayPolicy;
|
|
33
33
|
workDay: Record<string, unknown>;
|
|
@@ -99,7 +99,7 @@ export declare function runWorkdayStart(): Promise<{
|
|
|
99
99
|
grantCount: number;
|
|
100
100
|
} | null;
|
|
101
101
|
projectId: string;
|
|
102
|
-
environment: "local" | "
|
|
102
|
+
environment: "local" | "prod" | "staging";
|
|
103
103
|
workDayId: string;
|
|
104
104
|
state: string;
|
|
105
105
|
totalTasks: number;
|
|
@@ -186,7 +186,7 @@ export declare function runWorkdayStart(): Promise<{
|
|
|
186
186
|
grantCount: number;
|
|
187
187
|
} | null;
|
|
188
188
|
projectId: string;
|
|
189
|
-
environment: "local" | "
|
|
189
|
+
environment: "local" | "prod" | "staging";
|
|
190
190
|
workDayId: string;
|
|
191
191
|
state: string;
|
|
192
192
|
totalTasks: number;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@treeseed/agent",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.7",
|
|
4
4
|
"description": "Treeseed agent service runtime package.",
|
|
5
5
|
"license": "AGPL-3.0-only",
|
|
6
6
|
"repository": {
|
|
@@ -93,6 +93,7 @@
|
|
|
93
93
|
"setup:ci": "npm ci",
|
|
94
94
|
"build": "npm run build:dist",
|
|
95
95
|
"build:dist": "node ./scripts/run-ts.mjs ./scripts/build-dist.ts",
|
|
96
|
+
"prepare": "node ./scripts/prepare.mjs",
|
|
96
97
|
"dev:manager": "node ./scripts/run-ts.mjs ./src/services/manager.ts",
|
|
97
98
|
"dev:worker": "node ./scripts/run-ts.mjs ./src/services/worker.ts",
|
|
98
99
|
"dev:workday-start": "node ./scripts/run-ts.mjs ./src/services/workday-start.ts",
|
|
@@ -109,16 +110,16 @@
|
|
|
109
110
|
"prepack": "npm run build:dist",
|
|
110
111
|
"test:smoke": "node ./scripts/run-ts.mjs ./scripts/test-smoke.ts",
|
|
111
112
|
"verify:direct": "npm run release:verify",
|
|
112
|
-
"verify:local": "
|
|
113
|
-
"verify:action": "
|
|
114
|
-
"verify": "node
|
|
113
|
+
"verify:local": "TREESEED_VERIFY_DRIVER=direct node ./scripts/verify-driver.mjs",
|
|
114
|
+
"verify:action": "TREESEED_VERIFY_DRIVER=act node ./scripts/verify-driver.mjs",
|
|
115
|
+
"verify": "node ./scripts/verify-driver.mjs",
|
|
115
116
|
"release:setup": "npm run setup:ci",
|
|
116
117
|
"release:check-tag": "node ./scripts/run-ts.mjs ./scripts/assert-release-tag-version.ts",
|
|
117
118
|
"release:verify": "node ./scripts/run-ts.mjs ./scripts/release-verify.ts",
|
|
118
119
|
"release:publish": "node ./scripts/run-ts.mjs ./scripts/publish-package.ts"
|
|
119
120
|
},
|
|
120
121
|
"dependencies": {
|
|
121
|
-
"@treeseed/sdk": "0.8.
|
|
122
|
+
"@treeseed/sdk": "0.8.7",
|
|
122
123
|
"esbuild": "0.28.0",
|
|
123
124
|
"hono": "^4.8.2",
|
|
124
125
|
"typescript": "^5.9.3",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare const packageRoot: string;
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export {};
|