@treeseed/core 0.4.8 → 0.4.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -2
- package/dist/agent.d.ts +0 -1
- package/dist/agent.js +0 -2
- package/dist/agents/spec-types.d.ts +10 -10
- package/dist/api/agent-routes.d.ts +2 -2
- package/dist/api/agent-routes.js +51 -125
- package/dist/api/app.js +56 -4
- package/dist/api/auth/d1-store.d.ts +1 -0
- package/dist/api/auth/d1-store.js +21 -1
- package/dist/api/config.js +4 -0
- package/dist/api/http.d.ts +4 -0
- package/dist/api/http.js +7 -0
- package/dist/api/index.d.ts +1 -1
- package/dist/api/index.js +2 -2
- package/dist/api/operations-routes.d.ts +1 -0
- package/dist/api/operations-routes.js +6 -1
- package/dist/api/railway.d.ts +4 -0
- package/dist/api/sdk-dispatch.d.ts +2 -11
- package/dist/api/sdk-dispatch.js +1 -133
- package/dist/api/sdk-routes.d.ts +1 -0
- package/dist/api/sdk-routes.js +5 -1
- package/dist/api/types.d.ts +32 -16
- package/dist/dev.js +24 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -2
- package/dist/scripts/aggregate-book.js +13 -108
- package/dist/scripts/test-smoke.js +80 -24
- package/dist/services/common.d.ts +37 -4
- package/dist/services/common.js +135 -17
- package/dist/services/index.d.ts +1 -1
- package/dist/services/index.js +3 -2
- package/dist/services/remote-runner.d.ts +23 -0
- package/dist/services/remote-runner.js +105 -0
- package/dist/services/workday-report.js +13 -17
- package/dist/services/workday-start.d.ts +5 -1
- package/dist/services/workday-start.js +7 -13
- package/dist/services/worker.js +38 -57
- package/package.json +7 -11
- package/dist/api/gateway.d.ts +0 -5
- package/dist/api/gateway.js +0 -35
- package/dist/services/manager.d.ts +0 -4
- package/dist/services/manager.js +0 -199
|
@@ -2,5 +2,6 @@ import type { Hono } from 'hono';
|
|
|
2
2
|
import { executeHttpWorkflowOperation } from './operations.ts';
|
|
3
3
|
export declare function registerOperationRoutes(app: Hono<any>, options: {
|
|
4
4
|
scope: string;
|
|
5
|
+
prefix?: string;
|
|
5
6
|
executeOperation?: typeof executeHttpWorkflowOperation;
|
|
6
7
|
}): void;
|
|
@@ -3,7 +3,12 @@ import { executeHttpWorkflowOperation, isHttpWorkflowOperationAllowed } from "./
|
|
|
3
3
|
import { jsonError, requireScope } from "./http.js";
|
|
4
4
|
function registerOperationRoutes(app, options) {
|
|
5
5
|
const executeOperation = options.executeOperation ?? executeHttpWorkflowOperation;
|
|
6
|
-
|
|
6
|
+
const prefix = options.prefix ?? "";
|
|
7
|
+
function withPrefix(path) {
|
|
8
|
+
if (!prefix) return path;
|
|
9
|
+
return `${prefix}${path}`.replace(/\/{2,}/g, "/");
|
|
10
|
+
}
|
|
11
|
+
app.post(withPrefix("/operations/:operation"), async (c) => {
|
|
7
12
|
const unauthorized = requireScope(c, options.scope);
|
|
8
13
|
if (unauthorized) return unauthorized;
|
|
9
14
|
const requestedOperation = c.req.param("operation");
|
package/dist/api/railway.d.ts
CHANGED
|
@@ -22,7 +22,11 @@ export declare function createRailwayTreeseedApiServer(options?: ApiServerOption
|
|
|
22
22
|
baseUrl: string;
|
|
23
23
|
issuer: string;
|
|
24
24
|
repoRoot: string;
|
|
25
|
+
projectId: string;
|
|
25
26
|
authSecret: string;
|
|
27
|
+
projectApiKey?: string;
|
|
28
|
+
projectApiLabel: string;
|
|
29
|
+
projectApiPermissions: string[];
|
|
26
30
|
cloudflareAccountId?: string;
|
|
27
31
|
cloudflareApiToken?: string;
|
|
28
32
|
d1DatabaseId?: string;
|
|
@@ -1,14 +1,5 @@
|
|
|
1
1
|
import type { AgentSdk, RemoteSdkOperationRequest } from '@treeseed/sdk';
|
|
2
|
+
import { executeSdkOperation, findSdkOperation, listSdkOperationNames } from '@treeseed/sdk';
|
|
2
3
|
import type { ApiConfig } from './types.ts';
|
|
3
|
-
|
|
4
|
-
type SdkOperationHandler = (sdk: AgentSdk, input: JsonRecord) => Promise<unknown> | unknown;
|
|
5
|
-
interface SdkOperationSpec {
|
|
6
|
-
name: string;
|
|
7
|
-
aliases?: string[];
|
|
8
|
-
handler: SdkOperationHandler;
|
|
9
|
-
}
|
|
10
|
-
export declare function listSdkOperationNames(): string[];
|
|
11
|
-
export declare function findSdkOperation(name: string): SdkOperationSpec;
|
|
4
|
+
export { executeSdkOperation, findSdkOperation, listSdkOperationNames, };
|
|
12
5
|
export declare function resolveSdkInstance(sharedSdk: AgentSdk | undefined, config: ApiConfig, request: RemoteSdkOperationRequest): AgentSdk;
|
|
13
|
-
export declare function executeSdkOperation(sdk: AgentSdk, operationName: string, input: JsonRecord): Promise<unknown>;
|
|
14
|
-
export {};
|
package/dist/api/sdk-dispatch.js
CHANGED
|
@@ -1,142 +1,10 @@
|
|
|
1
|
-
import { AgentSdk as AgentSdkClass } from "@treeseed/sdk";
|
|
2
|
-
function passthrough(methodName) {
|
|
3
|
-
return (sdk, input) => sdk[methodName](input);
|
|
4
|
-
}
|
|
5
|
-
const SDK_OPERATION_SPECS = [
|
|
6
|
-
{ name: "get", handler: passthrough("get") },
|
|
7
|
-
{ name: "read", handler: passthrough("read") },
|
|
8
|
-
{ name: "search", handler: passthrough("search") },
|
|
9
|
-
{ name: "follow", handler: passthrough("follow") },
|
|
10
|
-
{ name: "pick", handler: passthrough("pick") },
|
|
11
|
-
{ name: "create", handler: passthrough("create") },
|
|
12
|
-
{ name: "update", handler: passthrough("update") },
|
|
13
|
-
{ name: "claimMessage", aliases: ["claim-message"], handler: passthrough("claimMessage") },
|
|
14
|
-
{ name: "ackMessage", aliases: ["ack-message"], handler: passthrough("ackMessage") },
|
|
15
|
-
{ name: "createMessage", aliases: ["create-message"], handler: passthrough("createMessage") },
|
|
16
|
-
{ name: "recordRun", aliases: ["record-run"], handler: passthrough("recordRun") },
|
|
17
|
-
{ name: "getCursor", aliases: ["get-cursor"], handler: passthrough("getCursor") },
|
|
18
|
-
{ name: "upsertCursor", aliases: ["upsert-cursor"], handler: passthrough("upsertCursor") },
|
|
19
|
-
{ name: "releaseLease", aliases: ["release-lease"], handler: passthrough("releaseLease") },
|
|
20
|
-
{
|
|
21
|
-
name: "releaseAllLeases",
|
|
22
|
-
aliases: ["release-all-leases"],
|
|
23
|
-
handler: (sdk) => sdk.releaseAllLeases()
|
|
24
|
-
},
|
|
25
|
-
{ name: "startWorkDay", aliases: ["start-work-day"], handler: passthrough("startWorkDay") },
|
|
26
|
-
{ name: "closeWorkDay", aliases: ["close-work-day"], handler: passthrough("closeWorkDay") },
|
|
27
|
-
{ name: "createTask", aliases: ["create-task"], handler: passthrough("createTask") },
|
|
28
|
-
{ name: "claimTask", aliases: ["claim-task"], handler: passthrough("claimTask") },
|
|
29
|
-
{
|
|
30
|
-
name: "recordTaskProgress",
|
|
31
|
-
aliases: ["record-task-progress"],
|
|
32
|
-
handler: passthrough("recordTaskProgress")
|
|
33
|
-
},
|
|
34
|
-
{ name: "completeTask", aliases: ["complete-task"], handler: passthrough("completeTask") },
|
|
35
|
-
{ name: "failTask", aliases: ["fail-task"], handler: passthrough("failTask") },
|
|
36
|
-
{ name: "appendTaskEvent", aliases: ["append-task-event"], handler: passthrough("appendTaskEvent") },
|
|
37
|
-
{ name: "searchTasks", aliases: ["search-tasks"], handler: passthrough("searchTasks") },
|
|
38
|
-
{
|
|
39
|
-
name: "getManagerContext",
|
|
40
|
-
aliases: ["get-manager-context"],
|
|
41
|
-
handler: (sdk, input) => sdk.getManagerContext(String(input.taskId ?? input.id ?? ""))
|
|
42
|
-
},
|
|
43
|
-
{ name: "createReport", aliases: ["create-report"], handler: passthrough("createReport") },
|
|
44
|
-
{
|
|
45
|
-
name: "listAgentSpecs",
|
|
46
|
-
aliases: ["list-agent-specs"],
|
|
47
|
-
handler: (sdk, input) => sdk.listAgentSpecs(input)
|
|
48
|
-
},
|
|
49
|
-
{ name: "refreshGraph", aliases: ["refresh-graph"], handler: passthrough("refreshGraph") },
|
|
50
|
-
{
|
|
51
|
-
name: "searchFiles",
|
|
52
|
-
aliases: ["search-files"],
|
|
53
|
-
handler: (sdk, input) => sdk.searchFiles(String(input.query ?? ""), input.options)
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
name: "searchSections",
|
|
57
|
-
aliases: ["search-sections"],
|
|
58
|
-
handler: (sdk, input) => sdk.searchSections(String(input.query ?? ""), input.options)
|
|
59
|
-
},
|
|
60
|
-
{
|
|
61
|
-
name: "searchEntities",
|
|
62
|
-
aliases: ["search-entities"],
|
|
63
|
-
handler: (sdk, input) => sdk.searchEntities(String(input.query ?? ""), input.options)
|
|
64
|
-
},
|
|
65
|
-
{
|
|
66
|
-
name: "getGraphNode",
|
|
67
|
-
aliases: ["get-graph-node"],
|
|
68
|
-
handler: (sdk, input) => sdk.getGraphNode(String(input.id ?? ""))
|
|
69
|
-
},
|
|
70
|
-
{
|
|
71
|
-
name: "getNeighbors",
|
|
72
|
-
aliases: ["get-neighbors"],
|
|
73
|
-
handler: (sdk, input) => sdk.getNeighbors(String(input.id ?? ""), input.options)
|
|
74
|
-
},
|
|
75
|
-
{
|
|
76
|
-
name: "followReferences",
|
|
77
|
-
aliases: ["follow-references"],
|
|
78
|
-
handler: (sdk, input) => sdk.followReferences(String(input.id ?? ""), input.options)
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
name: "getBacklinks",
|
|
82
|
-
aliases: ["get-backlinks"],
|
|
83
|
-
handler: (sdk, input) => sdk.getBacklinks(String(input.id ?? ""), input.options)
|
|
84
|
-
},
|
|
85
|
-
{
|
|
86
|
-
name: "getRelated",
|
|
87
|
-
aliases: ["get-related"],
|
|
88
|
-
handler: (sdk, input) => sdk.getRelated(String(input.id ?? ""), input.options)
|
|
89
|
-
},
|
|
90
|
-
{
|
|
91
|
-
name: "getSubgraph",
|
|
92
|
-
aliases: ["get-subgraph"],
|
|
93
|
-
handler: (sdk, input) => sdk.getSubgraph(Array.isArray(input.seedIds) ? input.seedIds.map(String) : [], input.options)
|
|
94
|
-
},
|
|
95
|
-
{ name: "resolveSeeds", aliases: ["resolve-seeds"], handler: passthrough("resolveSeeds") },
|
|
96
|
-
{ name: "queryGraph", aliases: ["query-graph"], handler: passthrough("queryGraph") },
|
|
97
|
-
{ name: "buildContextPack", aliases: ["build-context-pack"], handler: passthrough("buildContextPack") },
|
|
98
|
-
{
|
|
99
|
-
name: "parseGraphDsl",
|
|
100
|
-
aliases: ["parse-graph-dsl"],
|
|
101
|
-
handler: (sdk, input) => sdk.parseGraphDsl(String(input.source ?? input.query ?? ""))
|
|
102
|
-
},
|
|
103
|
-
{
|
|
104
|
-
name: "resolveReference",
|
|
105
|
-
aliases: ["resolve-reference"],
|
|
106
|
-
handler: (sdk, input) => sdk.resolveReference(String(input.reference ?? ""), input.options)
|
|
107
|
-
},
|
|
108
|
-
{
|
|
109
|
-
name: "explainReferenceChain",
|
|
110
|
-
aliases: ["explain-reference-chain"],
|
|
111
|
-
handler: (sdk, input) => sdk.explainReferenceChain(String(input.fromId ?? ""), String(input.toId ?? ""))
|
|
112
|
-
}
|
|
113
|
-
];
|
|
114
|
-
const SDK_OPERATION_INDEX = /* @__PURE__ */ new Map();
|
|
115
|
-
for (const spec of SDK_OPERATION_SPECS) {
|
|
116
|
-
SDK_OPERATION_INDEX.set(spec.name, spec);
|
|
117
|
-
for (const alias of spec.aliases ?? []) {
|
|
118
|
-
SDK_OPERATION_INDEX.set(alias, spec);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
function listSdkOperationNames() {
|
|
122
|
-
return [...new Set(SDK_OPERATION_SPECS.map((entry) => entry.name))];
|
|
123
|
-
}
|
|
124
|
-
function findSdkOperation(name) {
|
|
125
|
-
return SDK_OPERATION_INDEX.get(name) ?? null;
|
|
126
|
-
}
|
|
1
|
+
import { AgentSdk as AgentSdkClass, executeSdkOperation, findSdkOperation, listSdkOperationNames } from "@treeseed/sdk";
|
|
127
2
|
function resolveSdkInstance(sharedSdk, config, request) {
|
|
128
3
|
if (!request.repoRoot || request.repoRoot === config.repoRoot) {
|
|
129
4
|
return sharedSdk ?? new AgentSdkClass({ repoRoot: config.repoRoot });
|
|
130
5
|
}
|
|
131
6
|
return new AgentSdkClass({ repoRoot: request.repoRoot });
|
|
132
7
|
}
|
|
133
|
-
async function executeSdkOperation(sdk, operationName, input) {
|
|
134
|
-
const spec = findSdkOperation(operationName);
|
|
135
|
-
if (!spec) {
|
|
136
|
-
throw new Error(`Unknown SDK operation "${operationName}".`);
|
|
137
|
-
}
|
|
138
|
-
return await spec.handler(sdk, input);
|
|
139
|
-
}
|
|
140
8
|
export {
|
|
141
9
|
executeSdkOperation,
|
|
142
10
|
findSdkOperation,
|
package/dist/api/sdk-routes.d.ts
CHANGED
package/dist/api/sdk-routes.js
CHANGED
|
@@ -1,7 +1,11 @@
|
|
|
1
1
|
import { executeSdkOperation, resolveSdkInstance } from "./sdk-dispatch.js";
|
|
2
2
|
import { jsonError, requireScope } from "./http.js";
|
|
3
|
+
function withPrefix(prefix, path) {
|
|
4
|
+
if (!prefix) return path;
|
|
5
|
+
return `${prefix}${path}`.replace(/\/{2,}/g, "/");
|
|
6
|
+
}
|
|
3
7
|
function registerSdkRoutes(app, options) {
|
|
4
|
-
app.post("/sdk/:operation", async (c) => {
|
|
8
|
+
app.post(withPrefix(options.prefix ?? "", "/sdk/:operation"), async (c) => {
|
|
5
9
|
const unauthorized = requireScope(c, options.scope);
|
|
6
10
|
if (unauthorized) return unauthorized;
|
|
7
11
|
const operation = c.req.param("operation");
|
package/dist/api/types.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { Hono } from 'hono';
|
|
2
|
+
import type { AgentSdk } from '@treeseed/sdk';
|
|
2
3
|
import type { ApiPrincipal, ApiScope, DeviceCodeApproveRequest as SdkDeviceCodeApproveRequest, DeviceCodePollRequest, DeviceCodePollResponse, DeviceCodeStartRequest, DeviceCodeStartResponse, RemoteWorkflowOperationRequest as WorkflowHttpOperationRequest, RemoteWorkflowOperationResponse as ApiWorkflowOperationResponse, RemoteSdkOperationRequest as SdkHttpOperationRequest, TokenRefreshRequest, TokenRefreshResponse } from '@treeseed/sdk/remote';
|
|
3
4
|
export type { ApiPrincipal, ApiScope, DeviceCodePollRequest, DeviceCodePollResponse, DeviceCodeStartRequest, DeviceCodeStartResponse, WorkflowHttpOperationRequest, ApiWorkflowOperationResponse, SdkHttpOperationRequest, TokenRefreshRequest, TokenRefreshResponse, };
|
|
4
5
|
export type DeviceCodeApproveRequest = SdkDeviceCodeApproveRequest;
|
|
@@ -87,7 +88,11 @@ export interface ApiConfig {
|
|
|
87
88
|
baseUrl: string;
|
|
88
89
|
issuer: string;
|
|
89
90
|
repoRoot: string;
|
|
91
|
+
projectId: string;
|
|
90
92
|
authSecret: string;
|
|
93
|
+
projectApiKey?: string;
|
|
94
|
+
projectApiLabel: string;
|
|
95
|
+
projectApiPermissions: string[];
|
|
91
96
|
cloudflareAccountId?: string;
|
|
92
97
|
cloudflareApiToken?: string;
|
|
93
98
|
d1DatabaseId?: string;
|
|
@@ -111,11 +116,11 @@ export interface AppVariables {
|
|
|
111
116
|
principal: ApiPrincipal | null;
|
|
112
117
|
actingUser: ApiPrincipal | null;
|
|
113
118
|
credential: ApiCredential | null;
|
|
114
|
-
actorType: 'anonymous' | 'user' | 'service';
|
|
119
|
+
actorType: 'anonymous' | 'user' | 'service' | 'project';
|
|
115
120
|
permissionGrants: string[];
|
|
116
121
|
}
|
|
117
122
|
export interface ApiCredential {
|
|
118
|
-
type: 'access_token' | 'personal_access_token' | 'service_secret' | 'service_token';
|
|
123
|
+
type: 'access_token' | 'personal_access_token' | 'service_secret' | 'service_token' | 'project_api_key' | 'team_api_key';
|
|
119
124
|
id: string;
|
|
120
125
|
label?: string;
|
|
121
126
|
}
|
|
@@ -158,6 +163,28 @@ export interface ResolvedApiRuntimeProviders {
|
|
|
158
163
|
};
|
|
159
164
|
selections: ApiRuntimeProviderSelections;
|
|
160
165
|
}
|
|
166
|
+
export interface ApiResolvedSettings {
|
|
167
|
+
config: ApiConfig;
|
|
168
|
+
surfaces: {
|
|
169
|
+
auth: boolean;
|
|
170
|
+
templates: boolean;
|
|
171
|
+
sdk: boolean;
|
|
172
|
+
agent: boolean;
|
|
173
|
+
operations: boolean;
|
|
174
|
+
};
|
|
175
|
+
scopes: {
|
|
176
|
+
authMe: ApiScope;
|
|
177
|
+
sdk: ApiScope;
|
|
178
|
+
agent: ApiScope;
|
|
179
|
+
operations: ApiScope;
|
|
180
|
+
};
|
|
181
|
+
}
|
|
182
|
+
export interface ApiAppRuntime {
|
|
183
|
+
resolved: ApiResolvedSettings;
|
|
184
|
+
runtimeProviders: ResolvedApiRuntimeProviders;
|
|
185
|
+
sharedSdk: AgentSdk;
|
|
186
|
+
internalPrefix: string;
|
|
187
|
+
}
|
|
161
188
|
export interface ApiServerOptions {
|
|
162
189
|
config?: Partial<ApiConfig>;
|
|
163
190
|
runtimeProviders?: ApiRuntimeProviders;
|
|
@@ -176,18 +203,7 @@ export interface ApiServerOptions {
|
|
|
176
203
|
agent: ApiScope;
|
|
177
204
|
operations: ApiScope;
|
|
178
205
|
}>;
|
|
206
|
+
internalPrefix?: string;
|
|
207
|
+
extendApp?: (app: Hono<any>, runtime: ApiAppRuntime) => void;
|
|
179
208
|
log?: (message: string, details?: Record<string, unknown>) => void;
|
|
180
209
|
}
|
|
181
|
-
export interface GatewayQueueProducer {
|
|
182
|
-
enqueue(request: {
|
|
183
|
-
queueName?: string;
|
|
184
|
-
message: SdkQueueMessageEnvelope;
|
|
185
|
-
delaySeconds?: number;
|
|
186
|
-
}): Promise<void>;
|
|
187
|
-
}
|
|
188
|
-
export interface GatewayServerOptions {
|
|
189
|
-
sdk: AgentSdk;
|
|
190
|
-
bearerToken: string;
|
|
191
|
-
queueProducer?: GatewayQueueProducer;
|
|
192
|
-
projectId?: string;
|
|
193
|
-
}
|
package/dist/dev.js
CHANGED
|
@@ -38,6 +38,28 @@ function resolveNodeEntrypoint(packageDir, sourceRelativePath, distRelativePath)
|
|
|
38
38
|
args: [resolve(packageDir, distRelativePath)]
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
+
function resolveTenantApiEntrypoint(tenantRoot, runTsPath) {
|
|
42
|
+
const javascriptCandidates = [
|
|
43
|
+
resolve(tenantRoot, "src", "api", "server.js"),
|
|
44
|
+
resolve(tenantRoot, "src", "api", "server.mjs")
|
|
45
|
+
];
|
|
46
|
+
for (const candidate of javascriptCandidates) {
|
|
47
|
+
if (existsSync(candidate)) {
|
|
48
|
+
return {
|
|
49
|
+
command: process.execPath,
|
|
50
|
+
args: [candidate]
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const typescriptCandidate = resolve(tenantRoot, "src", "api", "server.ts");
|
|
55
|
+
if (existsSync(typescriptCandidate) && existsSync(runTsPath)) {
|
|
56
|
+
return {
|
|
57
|
+
command: process.execPath,
|
|
58
|
+
args: [runTsPath, typescriptCandidate]
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
41
63
|
function withWatchArgs(args, watchPaths) {
|
|
42
64
|
return watchPaths.flatMap((watchPath) => ["--watch-path", watchPath]).concat(args);
|
|
43
65
|
}
|
|
@@ -55,12 +77,13 @@ function createTreeseedIntegratedDevPlan(options = {}) {
|
|
|
55
77
|
const mergedEnv = { ...process.env, ...options.env ?? {} };
|
|
56
78
|
const apiBaseUrl = mergedEnv.TREESEED_API_BASE_URL?.trim() || `http://${apiHost}:${apiPort}`;
|
|
57
79
|
const sdkPackageRoot = resolvePackageRoot("@treeseed/sdk", tenantRoot);
|
|
80
|
+
const coreRunTsPath = resolve(packageRoot, "scripts", "run-ts.mjs");
|
|
58
81
|
const webEntrypoint = resolveNodeEntrypoint(
|
|
59
82
|
sdkPackageRoot,
|
|
60
83
|
"scripts/tenant-astro-command.ts",
|
|
61
84
|
"dist/scripts/tenant-astro-command.js"
|
|
62
85
|
);
|
|
63
|
-
const apiEntrypoint = resolveNodeEntrypoint(
|
|
86
|
+
const apiEntrypoint = resolveTenantApiEntrypoint(tenantRoot, coreRunTsPath) ?? resolveNodeEntrypoint(
|
|
64
87
|
packageRoot,
|
|
65
88
|
"src/api/server.ts",
|
|
66
89
|
"dist/api/server.js"
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,6 @@ export { buildTreeseedSiteLayers, resolveTreeseedPageEntrypoint, resolveTreeseed
|
|
|
2
2
|
export { buildTreeseedPlatformLayers, resolveTreeseedPlatformResource, TREESEED_PLATFORM_RESOURCE_KINDS, } from './platform-resources';
|
|
3
3
|
export { parseSiteConfig } from './utils/site-config-schema.js';
|
|
4
4
|
export { createTreeseedApiApp } from './api/app';
|
|
5
|
-
export { createTreeseedGatewayApp } from './api/gateway';
|
|
6
5
|
export { createRailwayTreeseedApiServer } from './api/railway';
|
|
7
6
|
export { resolveApiConfig } from './api/config';
|
|
8
7
|
export { createTreeseedIntegratedDevPlan, runTreeseedIntegratedDev, type TreeseedIntegratedDevCommand, type TreeseedIntegratedDevOptions, type TreeseedIntegratedDevPlan, type TreeseedIntegratedDevSurface, } from './dev';
|
package/dist/index.js
CHANGED
|
@@ -12,7 +12,6 @@ import {
|
|
|
12
12
|
} from "./platform-resources.js";
|
|
13
13
|
import { parseSiteConfig } from "./utils/site-config-schema.js";
|
|
14
14
|
import { createTreeseedApiApp } from "./api/app.js";
|
|
15
|
-
import { createTreeseedGatewayApp } from "./api/gateway.js";
|
|
16
15
|
import { createRailwayTreeseedApiServer } from "./api/railway.js";
|
|
17
16
|
import { resolveApiConfig } from "./api/config.js";
|
|
18
17
|
import {
|
|
@@ -26,7 +25,6 @@ export {
|
|
|
26
25
|
buildTreeseedSiteLayers,
|
|
27
26
|
createRailwayTreeseedApiServer,
|
|
28
27
|
createTreeseedApiApp,
|
|
29
|
-
createTreeseedGatewayApp,
|
|
30
28
|
createTreeseedIntegratedDevPlan,
|
|
31
29
|
parseSiteConfig,
|
|
32
30
|
resolveApiConfig,
|
|
@@ -1,112 +1,17 @@
|
|
|
1
|
-
import fs from 'node:fs';
|
|
2
1
|
import path from 'node:path';
|
|
3
|
-
import {
|
|
2
|
+
import { exportTenantBookPackages } from '@treeseed/sdk/platform/book-export';
|
|
4
3
|
import { PROJECT_TENANT } from '../tenant/bridge.js';
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
}
|
|
11
|
-
function getSidebarOrder(filePath) {
|
|
12
|
-
const rawContent = fs.readFileSync(filePath, 'utf8');
|
|
13
|
-
const frontmatterMatch = rawContent.match(/^---\r?\n([\s\S]*?)\r?\n---/);
|
|
14
|
-
if (!frontmatterMatch)
|
|
15
|
-
return Number.POSITIVE_INFINITY;
|
|
16
|
-
const orderMatch = frontmatterMatch[1].match(/^\s{2}order:\s*(\d+)\s*$/m);
|
|
17
|
-
return orderMatch ? Number.parseInt(orderMatch[1], 10) : Number.POSITIVE_INFINITY;
|
|
18
|
-
}
|
|
19
|
-
function collectMarkdownFiles(rootPath) {
|
|
20
|
-
if (!fs.existsSync(rootPath)) {
|
|
21
|
-
throw new Error(`Book export root not found: ${rootPath}`);
|
|
22
|
-
}
|
|
23
|
-
const stats = fs.statSync(rootPath);
|
|
24
|
-
if (stats.isFile()) {
|
|
25
|
-
return [rootPath];
|
|
26
|
-
}
|
|
27
|
-
const entries = fs.readdirSync(rootPath, { withFileTypes: true });
|
|
28
|
-
return sortPaths(entries.flatMap((entry) => {
|
|
29
|
-
const fullPath = path.join(rootPath, entry.name);
|
|
30
|
-
if (entry.isDirectory()) {
|
|
31
|
-
return collectMarkdownFiles(fullPath);
|
|
32
|
-
}
|
|
33
|
-
if (entry.isFile() && (entry.name.endsWith('.md') || entry.name.endsWith('.mdx'))) {
|
|
34
|
-
return [fullPath];
|
|
35
|
-
}
|
|
36
|
-
return [];
|
|
37
|
-
}));
|
|
38
|
-
}
|
|
39
|
-
function stripFrontmatter(content) {
|
|
40
|
-
return content.replace(/^---\r?\n[\s\S]*?\r?\n---\r?\n?/, '').trim();
|
|
41
|
-
}
|
|
42
|
-
function stripMdxOnlySyntax(content) {
|
|
43
|
-
return content
|
|
44
|
-
.replace(/^import\s.+$/gm, '')
|
|
45
|
-
.replace(/^\s*<\/?[A-Z][^>]*>\s*$/gm, '')
|
|
46
|
-
.replace(/\n{3,}/g, '\n\n')
|
|
47
|
-
.trim();
|
|
48
|
-
}
|
|
49
|
-
function inferExportRootFromBasePath(book) {
|
|
50
|
-
const normalizedBasePath = String(book.basePath || '').trim();
|
|
51
|
-
const knowledgePrefix = '/knowledge/';
|
|
52
|
-
if (!normalizedBasePath.startsWith(knowledgePrefix)) {
|
|
53
|
-
throw new Error(`Book basePath must start with "${knowledgePrefix}" to infer exports: ${book.basePath}`);
|
|
54
|
-
}
|
|
55
|
-
const relativeKnowledgePath = normalizedBasePath
|
|
56
|
-
.slice(knowledgePrefix.length)
|
|
57
|
-
.replace(/^\/+|\/+$/g, '');
|
|
58
|
-
if (!relativeKnowledgePath) {
|
|
59
|
-
throw new Error(`Book basePath must identify a knowledge directory: ${book.basePath}`);
|
|
60
|
-
}
|
|
61
|
-
return path.join(PROJECT_TENANT.content.docs, relativeKnowledgePath);
|
|
62
|
-
}
|
|
63
|
-
function resolveExportRoots(book) {
|
|
64
|
-
if (Array.isArray(book.exportRoots) && book.exportRoots.length > 0) {
|
|
65
|
-
return book.exportRoots;
|
|
66
|
-
}
|
|
67
|
-
return [inferExportRootFromBasePath(book)];
|
|
68
|
-
}
|
|
69
|
-
function resolveBookFiles(book) {
|
|
70
|
-
const files = resolveExportRoots(book).flatMap((root) => collectMarkdownFiles(path.resolve(projectRoot, root)).sort((left, right) => {
|
|
71
|
-
const orderDelta = getSidebarOrder(left) - getSidebarOrder(right);
|
|
72
|
-
if (orderDelta !== 0)
|
|
73
|
-
return orderDelta;
|
|
74
|
-
return left.localeCompare(right, undefined, { numeric: true, sensitivity: 'base' });
|
|
75
|
-
}));
|
|
76
|
-
return Array.from(new Set(files));
|
|
77
|
-
}
|
|
78
|
-
function buildBookMarkdown(book) {
|
|
79
|
-
const sections = resolveBookFiles(book).map((filePath) => {
|
|
80
|
-
const rawContent = fs.readFileSync(filePath, 'utf8');
|
|
81
|
-
return stripMdxOnlySyntax(stripFrontmatter(rawContent));
|
|
82
|
-
});
|
|
83
|
-
return `# ${book.downloadTitle}\n\n> This document is auto-generated from the TreeSeed knowledge source.\n\n${sections.join('\n\n---\n\n')}\n`;
|
|
84
|
-
}
|
|
85
|
-
function ensureOutputDir() {
|
|
86
|
-
fs.mkdirSync(outputDir, { recursive: true });
|
|
87
|
-
}
|
|
88
|
-
function writeBookOutput(fileName, content) {
|
|
89
|
-
const outputPath = path.join(outputDir, fileName);
|
|
90
|
-
fs.writeFileSync(outputPath, content);
|
|
91
|
-
return outputPath;
|
|
92
|
-
}
|
|
93
|
-
function main() {
|
|
94
|
-
console.log('Generating TreeSeed knowledge exports...');
|
|
95
|
-
ensureOutputDir();
|
|
96
|
-
const bookOutputs = BOOKS.map((book) => {
|
|
97
|
-
const content = buildBookMarkdown(book);
|
|
98
|
-
const outputPath = writeBookOutput(book.downloadFileName, content);
|
|
99
|
-
console.log(`Generated ${path.relative(projectRoot, outputPath)}`);
|
|
100
|
-
return { book, content };
|
|
101
|
-
});
|
|
102
|
-
const compositeContent = `# ${TREESEED_LIBRARY_DOWNLOAD.downloadTitle}\n\n> This document is auto-generated from the TreeSeed knowledge source.\n\n${bookOutputs
|
|
103
|
-
.map(({ content }) => content.trim())
|
|
104
|
-
.join('\n\n---\n\n')}\n`;
|
|
105
|
-
const compositeOutputPath = writeBookOutput(TREESEED_LIBRARY_DOWNLOAD.downloadFileName, compositeContent);
|
|
106
|
-
console.log(`Generated ${path.relative(projectRoot, compositeOutputPath)}`);
|
|
107
|
-
if (fs.existsSync(legacyOutputFile)) {
|
|
108
|
-
fs.rmSync(legacyOutputFile);
|
|
109
|
-
console.log(`Removed legacy export ${path.relative(projectRoot, legacyOutputFile)}`);
|
|
4
|
+
async function main() {
|
|
5
|
+
console.log('Generating Treeseed AI book packages...');
|
|
6
|
+
const result = await exportTenantBookPackages({ projectRoot: PROJECT_TENANT.__tenantRoot ?? process.cwd() });
|
|
7
|
+
for (const entry of result.bookPackages) {
|
|
8
|
+
console.log(`Generated ${path.relative(result.projectRoot, entry.markdownPath)}`);
|
|
9
|
+
console.log(`Generated ${path.relative(result.projectRoot, entry.indexPath)}`);
|
|
110
10
|
}
|
|
11
|
+
console.log(`Generated ${path.relative(result.projectRoot, result.libraryPackage.markdownPath)}`);
|
|
12
|
+
console.log(`Generated ${path.relative(result.projectRoot, result.libraryPackage.indexPath)}`);
|
|
111
13
|
}
|
|
112
|
-
main()
|
|
14
|
+
main().catch((error) => {
|
|
15
|
+
console.error(error instanceof Error ? error.message : String(error));
|
|
16
|
+
process.exitCode = 1;
|
|
17
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, readdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { mkdtempSync } from 'node:fs';
|
|
3
3
|
import { tmpdir } from 'node:os';
|
|
4
4
|
import { dirname, join, resolve } from 'node:path';
|
|
@@ -24,36 +24,92 @@ function run(command, args, cwd = packageRoot, capture = false) {
|
|
|
24
24
|
}
|
|
25
25
|
return (result.stdout ?? '').trim();
|
|
26
26
|
}
|
|
27
|
-
function
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
27
|
+
function runtimeDependencyNamesFor(root) {
|
|
28
|
+
const packageJson = JSON.parse(readFileSync(resolve(root, 'package.json'), 'utf8'));
|
|
29
|
+
return Object.keys(packageJson.dependencies ?? {});
|
|
30
|
+
}
|
|
31
|
+
function resolveWorkspaceRuntimePackageRoots() {
|
|
32
|
+
const roots = new Map();
|
|
33
|
+
for (const dependencyName of runtimeDependencyNamesFor(packageRoot)) {
|
|
34
|
+
const dependencyRoot = resolveTreeseedRuntimeDependencyRoot(dependencyName);
|
|
35
|
+
if (dependencyRoot) {
|
|
36
|
+
roots.set(dependencyName, dependencyRoot);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return roots;
|
|
40
|
+
}
|
|
41
|
+
function collectRuntimeDependenciesForPackaging() {
|
|
42
|
+
const dependencyNames = new Set(runtimeDependencyNamesFor(packageRoot));
|
|
43
|
+
const searchRoots = [
|
|
44
|
+
packageRoot,
|
|
45
|
+
sdkPackageRoot,
|
|
46
|
+
];
|
|
47
|
+
const queue = [...resolveWorkspaceRuntimePackageRoots().values()];
|
|
48
|
+
const visited = new Set();
|
|
49
|
+
while (queue.length > 0) {
|
|
50
|
+
const nextRoot = queue.shift();
|
|
51
|
+
if (!nextRoot || visited.has(nextRoot)) {
|
|
52
|
+
continue;
|
|
35
53
|
}
|
|
36
|
-
|
|
54
|
+
visited.add(nextRoot);
|
|
55
|
+
for (const dependencyName of runtimeDependencyNamesFor(nextRoot)) {
|
|
56
|
+
dependencyNames.add(dependencyName);
|
|
57
|
+
const dependencyRoot = resolveTreeseedRuntimeDependencyRoot(dependencyName, searchRoots);
|
|
58
|
+
if (dependencyRoot) {
|
|
59
|
+
queue.push(dependencyRoot);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return dependencyNames;
|
|
64
|
+
}
|
|
65
|
+
function resolveTreeseedRuntimeDependencyRoot(packageName, searchRoots = [packageRoot, sdkPackageRoot]) {
|
|
66
|
+
if (!packageName.startsWith('@treeseed/')) {
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
69
|
+
const folderName = packageName.slice('@treeseed/'.length);
|
|
70
|
+
const workspaceCandidateRoot = resolve(packageRoot, '..', folderName);
|
|
71
|
+
if (existsSync(resolve(workspaceCandidateRoot, 'package.json'))) {
|
|
72
|
+
return workspaceCandidateRoot;
|
|
73
|
+
}
|
|
74
|
+
try {
|
|
75
|
+
return resolveInstalledPackageRoot(packageName, searchRoots);
|
|
76
|
+
}
|
|
77
|
+
catch {
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
function resolveInstalledPackageRoot(packageName, searchRoots) {
|
|
82
|
+
let resolvedEntry = require.resolve(packageName, { paths: searchRoots });
|
|
83
|
+
let current = dirname(resolvedEntry);
|
|
84
|
+
while (true) {
|
|
85
|
+
const packageJsonPath = resolve(current, 'package.json');
|
|
86
|
+
if (existsSync(packageJsonPath)) {
|
|
87
|
+
return current;
|
|
37
88
|
}
|
|
38
89
|
const parent = resolve(current, '..');
|
|
39
|
-
if (parent === current)
|
|
40
|
-
|
|
90
|
+
if (parent === current) {
|
|
91
|
+
throw new Error(`Unable to resolve installed package root for ${packageName}.`);
|
|
92
|
+
}
|
|
41
93
|
current = parent;
|
|
42
94
|
}
|
|
43
|
-
if (lastCandidate) {
|
|
44
|
-
return lastCandidate;
|
|
45
|
-
}
|
|
46
|
-
throw new Error(`Unable to locate node_modules for ${packageRoot}.`);
|
|
47
95
|
}
|
|
48
|
-
function mirrorDependencies(tempRoot) {
|
|
49
|
-
const
|
|
50
|
-
|
|
51
|
-
|
|
96
|
+
function mirrorDependencies(tempRoot, excludedPackages = new Set()) {
|
|
97
|
+
const runtimeDependencies = collectRuntimeDependenciesForPackaging();
|
|
98
|
+
const searchRoots = [
|
|
99
|
+
packageRoot,
|
|
100
|
+
...resolveWorkspaceRuntimePackageRoots().values(),
|
|
101
|
+
];
|
|
102
|
+
for (const packageName of runtimeDependencies) {
|
|
103
|
+
if (excludedPackages.has(packageName) || packageName === '@treeseed/core') {
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
const sourcePath = resolveInstalledPackageRoot(packageName, searchRoots);
|
|
107
|
+
const targetPath = resolve(tempRoot, 'node_modules', ...packageName.split('/'));
|
|
108
|
+
if (existsSync(targetPath)) {
|
|
52
109
|
continue;
|
|
53
110
|
}
|
|
54
|
-
const targetPath = resolve(tempRoot, 'node_modules', entry.name);
|
|
55
111
|
mkdirSync(dirname(targetPath), { recursive: true });
|
|
56
|
-
symlinkSync(
|
|
112
|
+
symlinkSync(sourcePath, targetPath, 'dir');
|
|
57
113
|
}
|
|
58
114
|
}
|
|
59
115
|
function pack(root, outputRoot, fallbackName) {
|
|
@@ -98,6 +154,7 @@ try {
|
|
|
98
154
|
mkdirSync(packRoot, { recursive: true });
|
|
99
155
|
mkdirSync(extractRoot, { recursive: true });
|
|
100
156
|
const coreTarball = pack(packageRoot, packRoot, 'treeseed-core.tgz');
|
|
157
|
+
const workspaceRuntimePackageRoots = resolveWorkspaceRuntimePackageRoots();
|
|
101
158
|
if (existsSync(resolve(sdkPackageRoot, 'scripts', 'run-ts.mjs'))) {
|
|
102
159
|
const sdkTarball = pack(sdkPackageRoot, packRoot, 'treeseed-sdk.tgz');
|
|
103
160
|
installPackagedPackage(extractRoot, installRoot, sdkTarball, 'sdk');
|
|
@@ -106,7 +163,7 @@ try {
|
|
|
106
163
|
installPackageDirectory(installRoot, sdkPackageRoot, 'sdk');
|
|
107
164
|
}
|
|
108
165
|
installPackagedPackage(extractRoot, installRoot, coreTarball, 'core');
|
|
109
|
-
mirrorDependencies(installRoot);
|
|
166
|
+
mirrorDependencies(installRoot, new Set(workspaceRuntimePackageRoots.keys()));
|
|
110
167
|
writeFileSync(resolve(installRoot, 'package.json'), `${JSON.stringify({ name: 'treeseed-core-smoke', private: true, type: 'module' }, null, 2)}\n`, 'utf8');
|
|
111
168
|
run(process.execPath, [
|
|
112
169
|
'--input-type=module',
|
|
@@ -117,7 +174,6 @@ try {
|
|
|
117
174
|
'await import("@treeseed/core/runtime-types");',
|
|
118
175
|
'await import("@treeseed/core/contracts/messages");',
|
|
119
176
|
'await import("@treeseed/core/contracts/run");',
|
|
120
|
-
'await import("@treeseed/core/services/manager");',
|
|
121
177
|
'await import("@treeseed/core/services/worker");',
|
|
122
178
|
'await import("@treeseed/core/services/workday-start");',
|
|
123
179
|
'await import("@treeseed/core/services/workday-report");',
|