@treeseed/core 0.4.6 → 0.4.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.
Files changed (65) hide show
  1. package/README.md +8 -16
  2. package/dist/agent-runtime.d.ts +17 -0
  3. package/dist/agent-runtime.js +111 -0
  4. package/dist/agent.d.ts +11 -0
  5. package/dist/agent.js +25 -0
  6. package/dist/agents/adapters/execution.d.ts +46 -0
  7. package/dist/agents/adapters/execution.js +90 -0
  8. package/dist/agents/adapters/mutations.d.ts +22 -0
  9. package/dist/agents/adapters/mutations.js +30 -0
  10. package/dist/agents/adapters/notification.d.ts +11 -0
  11. package/dist/agents/adapters/notification.js +16 -0
  12. package/dist/agents/adapters/repository.d.ts +23 -0
  13. package/dist/agents/adapters/repository.js +61 -0
  14. package/dist/agents/adapters/research.d.ts +14 -0
  15. package/dist/agents/adapters/research.js +25 -0
  16. package/dist/agents/adapters/verification.d.ts +36 -0
  17. package/dist/agents/adapters/verification.js +62 -0
  18. package/dist/agents/cli-tools.d.ts +1 -0
  19. package/dist/agents/cli-tools.js +5 -0
  20. package/dist/agents/cli.d.ts +15 -0
  21. package/dist/agents/cli.js +109 -0
  22. package/dist/agents/contracts/messages.d.ts +88 -0
  23. package/dist/agents/contracts/messages.js +138 -0
  24. package/dist/agents/contracts/run.d.ts +20 -0
  25. package/dist/agents/contracts/run.js +0 -0
  26. package/dist/agents/index.d.ts +1 -0
  27. package/dist/agents/index.js +5 -0
  28. package/dist/agents/kernel/agent-kernel.d.ts +51 -0
  29. package/dist/agents/kernel/agent-kernel.js +285 -0
  30. package/dist/agents/kernel/trigger-resolver.d.ts +18 -0
  31. package/dist/agents/kernel/trigger-resolver.js +153 -0
  32. package/dist/agents/registry-helper.d.ts +4 -0
  33. package/dist/agents/registry-helper.js +14 -0
  34. package/dist/agents/registry.d.ts +6 -0
  35. package/dist/agents/registry.js +98 -0
  36. package/dist/agents/runtime-types.d.ts +117 -0
  37. package/dist/agents/runtime-types.js +0 -0
  38. package/dist/agents/spec-loader.d.ts +18 -0
  39. package/dist/agents/spec-loader.js +55 -0
  40. package/dist/agents/spec-normalizer.d.ts +2 -0
  41. package/dist/agents/spec-normalizer.js +257 -0
  42. package/dist/agents/spec-types.d.ts +64 -0
  43. package/dist/agents/spec-types.js +0 -0
  44. package/dist/agents/testing/agents-smoke.d.ts +1 -0
  45. package/dist/agents/testing/agents-smoke.js +32 -0
  46. package/dist/agents/testing/e2e-harness.d.ts +44 -0
  47. package/dist/agents/testing/e2e-harness.js +504 -0
  48. package/dist/api/agent-routes.js +2 -10
  49. package/dist/scripts/build-dist.js +5 -0
  50. package/dist/scripts/run-fixture-astro-command.js +2 -170
  51. package/dist/scripts/test-smoke.js +15 -1
  52. package/dist/scripts/workspace-bootstrap.js +0 -1
  53. package/dist/services/common.d.ts +20 -0
  54. package/dist/services/common.js +66 -0
  55. package/dist/services/index.d.ts +4 -0
  56. package/dist/services/index.js +11 -0
  57. package/dist/services/manager.d.ts +4 -0
  58. package/dist/services/manager.js +199 -0
  59. package/dist/services/workday-report.d.ts +17 -0
  60. package/dist/services/workday-report.js +44 -0
  61. package/dist/services/workday-start.d.ts +2 -0
  62. package/dist/services/workday-start.js +27 -0
  63. package/dist/services/worker.d.ts +6 -0
  64. package/dist/services/worker.js +108 -0
  65. package/package.json +43 -2
@@ -1,4 +1,4 @@
1
- import { existsSync, mkdirSync, rmSync, symlinkSync, writeFileSync } from 'node:fs';
1
+ import { existsSync, mkdirSync, rmSync, symlinkSync } from 'node:fs';
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import { dirname, resolve } from 'node:path';
4
4
  import { createRequire } from 'node:module';
@@ -54,176 +54,8 @@ function ensureFixtureWorkspacePackage(packageName, workspaceDir) {
54
54
  rmSync(packageDir, { recursive: true, force: true });
55
55
  symlinkSync(resolvedPackageRoot, packageDir, 'dir');
56
56
  }
57
- function ensureFixtureAgentContractPackage() {
58
- const packageDir = resolve(fixtureRoot, 'node_modules', '@treeseed', 'agent');
59
- mkdirSync(resolve(packageDir, 'contracts'), { recursive: true });
60
- writeFileSync(resolve(packageDir, 'package.json'), JSON.stringify({
61
- name: '@treeseed/agent',
62
- type: 'module',
63
- exports: {
64
- './runtime-types': {
65
- types: './runtime-types.d.js',
66
- default: './runtime-types.js',
67
- },
68
- './contracts/messages': {
69
- types: './contracts/messages.d.js',
70
- default: './contracts/messages.js',
71
- },
72
- './contracts/run': {
73
- types: './contracts/run.d.js',
74
- default: './contracts/run.js',
75
- },
76
- },
77
- }, null, 2), 'utf8');
78
- writeFileSync(resolve(packageDir, 'runtime-types.js'), 'export {};\n', 'utf8');
79
- writeFileSync(resolve(packageDir, 'runtime-types.d.ts'), [
80
- "import type { AgentHandlerKind, AgentRunStatus } from '@treeseed/sdk/types/agents';",
81
- 'export interface AgentTriggerInvocation {',
82
- "\tkind: 'startup' | 'schedule' | 'message' | 'manual' | 'follow';",
83
- '\tsource: string;',
84
- '\tmessage?: { id?: string | number; type?: string; payloadJson?: string | null } | null;',
85
- '}',
86
- 'export interface AgentExecutionResult {',
87
- '\tstatus: AgentRunStatus;',
88
- '\tsummary: string;',
89
- '\tstdout?: string;',
90
- '\tstderr?: string;',
91
- "\terrorCategory?: import('./contracts/run.js').AgentErrorCategory | null;",
92
- '\tmetadata?: Record<string, unknown>;',
93
- '}',
94
- 'export interface AgentContext {',
95
- '\trunId: string;',
96
- '\trepoRoot: string;',
97
- '\tagent: any;',
98
- '\tsdk: any;',
99
- '\ttrigger: AgentTriggerInvocation;',
100
- '\texecution: any;',
101
- '\tmutations: any;',
102
- '\trepository: any;',
103
- '\tverification: any;',
104
- '\tnotifications: any;',
105
- '\tresearch: any;',
106
- '}',
107
- 'export interface AgentHandler<TInputs = unknown, TResult = unknown> {',
108
- '\tkind: AgentHandlerKind;',
109
- '\tresolveInputs(context: AgentContext): Promise<TInputs>;',
110
- '\texecute(context: AgentContext, inputs: TInputs): Promise<TResult>;',
111
- '\temitOutputs(context: AgentContext, result: TResult): Promise<AgentExecutionResult>;',
112
- '}',
113
- '',
114
- ].join('\n'), 'utf8');
115
- writeFileSync(resolve(packageDir, 'contracts', 'messages.js'), [
116
- 'export const AGENT_MESSAGE_TYPES = {};',
117
- 'export function parseAgentMessagePayload(_type, payloadJson) {',
118
- '\treturn JSON.parse(payloadJson);',
119
- '}',
120
- '',
121
- ].join('\n'), 'utf8');
122
- writeFileSync(resolve(packageDir, 'contracts', 'messages.d.ts'), [
123
- 'export interface QuestionPriorityUpdatedMessage {',
124
- '\tquestionId: string;',
125
- '\treason: string;',
126
- '\tplannerRunId: string;',
127
- '}',
128
- 'export interface ObjectivePriorityUpdatedMessage {',
129
- '\tobjectiveId: string;',
130
- '\treason: string;',
131
- '\tplannerRunId: string;',
132
- '}',
133
- 'export interface ArchitectureUpdatedMessage {',
134
- '\tobjectiveId: string;',
135
- '\tknowledgeId: string;',
136
- '\tarchitectRunId: string;',
137
- '}',
138
- 'export interface SubscriberNotifiedMessage {',
139
- '\temail: string;',
140
- '\titemCount: number;',
141
- '\tnotifierRunId: string;',
142
- '}',
143
- 'export interface ResearchStartedMessage {',
144
- '\tquestionId: string;',
145
- '\tresearcherRunId: string;',
146
- '}',
147
- 'export interface ResearchCompletedMessage {',
148
- '\tquestionId: string;',
149
- '\tknowledgeId: string | null;',
150
- '\tresearcherRunId: string;',
151
- '}',
152
- 'export interface TaskCompleteMessage {',
153
- '\tbranchName: string | null;',
154
- '\tchangedTargets: string[];',
155
- '\tengineerRunId: string;',
156
- '}',
157
- 'export interface TaskWaitingMessage {',
158
- '\tblockingReason: string;',
159
- '\tengineerRunId: string;',
160
- '}',
161
- 'export interface TaskFailedMessage {',
162
- '\tfailureSummary: string;',
163
- '\tengineerRunId: string;',
164
- '}',
165
- 'export interface TaskVerifiedMessage {',
166
- '\tbranchName: string | null;',
167
- '\treviewerRunId: string;',
168
- '}',
169
- 'export interface ReviewFailedMessage {',
170
- '\tfailureSummary: string;',
171
- '\treviewerRunId: string;',
172
- '}',
173
- 'export interface ReviewWaitingMessage {',
174
- '\tblockingReason: string;',
175
- '\treviewerRunId: string;',
176
- '}',
177
- 'export interface ReleaseStartedMessage {',
178
- '\ttaskRunId: string | null;',
179
- '\treleaserRunId: string;',
180
- '}',
181
- 'export interface ReleaseCompletedMessage {',
182
- '\treleaseSummary: string;',
183
- '\treleaserRunId: string;',
184
- '}',
185
- 'export interface ReleaseFailedMessage {',
186
- '\tfailureSummary: string;',
187
- '\treleaserRunId: string;',
188
- '}',
189
- 'export interface AgentMessageContracts {',
190
- '\tquestion_priority_updated: QuestionPriorityUpdatedMessage;',
191
- '\tobjective_priority_updated: ObjectivePriorityUpdatedMessage;',
192
- '\tarchitecture_updated: ArchitectureUpdatedMessage;',
193
- '\tsubscriber_notified: SubscriberNotifiedMessage;',
194
- '\tresearch_started: ResearchStartedMessage;',
195
- '\tresearch_completed: ResearchCompletedMessage;',
196
- '\ttask_complete: TaskCompleteMessage;',
197
- '\ttask_waiting: TaskWaitingMessage;',
198
- '\ttask_failed: TaskFailedMessage;',
199
- '\ttask_verified: TaskVerifiedMessage;',
200
- '\treview_failed: ReviewFailedMessage;',
201
- '\treview_waiting: ReviewWaitingMessage;',
202
- '\trelease_started: ReleaseStartedMessage;',
203
- '\trelease_completed: ReleaseCompletedMessage;',
204
- '\trelease_failed: ReleaseFailedMessage;',
205
- '}',
206
- 'export type AgentMessageType = keyof AgentMessageContracts;',
207
- 'export type AgentMessagePayload<TType extends AgentMessageType> = AgentMessageContracts[TType];',
208
- 'export declare const AGENT_MESSAGE_TYPES: readonly AgentMessageType[];',
209
- 'export declare function parseAgentMessagePayload<TType extends AgentMessageType>(_type: TType, payloadJson: string): AgentMessagePayload<TType>;',
210
- '',
211
- ].join('\n'), 'utf8');
212
- writeFileSync(resolve(packageDir, 'contracts', 'run.js'), 'export {};\n', 'utf8');
213
- writeFileSync(resolve(packageDir, 'contracts', 'run.d.ts'), [
214
- "export type AgentErrorCategory = 'execution_error' | 'mutation_error' | 'verification_error' | 'notification_error' | 'research_error' | 'sdk_error' | 'unknown';",
215
- '',
216
- ].join('\n'), 'utf8');
217
- }
218
57
  ensureFixtureWorkspacePackage('@treeseed/sdk', resolve(packageRoot, '..', 'sdk'));
219
- const workspaceAgentRoot = resolve(packageRoot, '..', 'agent');
220
- if (existsSync(workspaceAgentRoot) || resolveInstalledPackageRoot('@treeseed/agent')) {
221
- ensureFixtureWorkspacePackage('@treeseed/agent', workspaceAgentRoot);
222
- }
223
- else {
224
- rmSync(resolve(fixtureRoot, 'node_modules', '@treeseed', 'agent'), { recursive: true, force: true });
225
- ensureFixtureAgentContractPackage();
226
- }
58
+ ensureFixtureWorkspacePackage('@treeseed/core', packageRoot);
227
59
  const result = spawnSync('npx', ['astro', command, '--root', fixtureRoot, ...rest], {
228
60
  cwd: packageRoot,
229
61
  stdio: 'inherit',
@@ -108,7 +108,21 @@ try {
108
108
  installPackagedPackage(extractRoot, installRoot, coreTarball, 'core');
109
109
  mirrorDependencies(installRoot);
110
110
  writeFileSync(resolve(installRoot, 'package.json'), `${JSON.stringify({ name: 'treeseed-core-smoke', private: true, type: 'module' }, null, 2)}\n`, 'utf8');
111
- run(process.execPath, ['--input-type=module', '-e', 'await import("@treeseed/core");'], installRoot);
111
+ run(process.execPath, [
112
+ '--input-type=module',
113
+ '-e',
114
+ [
115
+ 'await import("@treeseed/core");',
116
+ 'await import("@treeseed/core/agent/cli");',
117
+ 'await import("@treeseed/core/runtime-types");',
118
+ 'await import("@treeseed/core/contracts/messages");',
119
+ 'await import("@treeseed/core/contracts/run");',
120
+ 'await import("@treeseed/core/services/manager");',
121
+ 'await import("@treeseed/core/services/worker");',
122
+ 'await import("@treeseed/core/services/workday-start");',
123
+ 'await import("@treeseed/core/services/workday-report");',
124
+ ].join(' '),
125
+ ], installRoot);
112
126
  console.log('Core packed-install smoke passed.');
113
127
  }
114
128
  finally {
@@ -8,7 +8,6 @@ const require = createRequire(import.meta.url);
8
8
  const requiredPackages = [
9
9
  { name: '@treeseed/sdk', dir: 'packages/sdk', build: true },
10
10
  { name: '@treeseed/core', dir: 'packages/core', build: true },
11
- { name: '@treeseed/agent', dir: 'packages/agent', build: true },
12
11
  { name: '@treeseed/cli', dir: 'packages/cli', build: true, binName: 'treeseed' },
13
12
  ];
14
13
  function packageState(root, entry) {
@@ -0,0 +1,20 @@
1
+ import { AgentSdk } from '@treeseed/sdk/sdk';
2
+ import { TreeseedGatewayClient, CloudflareQueuePullClient } from '@treeseed/sdk/remote';
3
+ export declare function resolveServiceRepoRoot(): string;
4
+ export declare function createServiceSdk(): AgentSdk;
5
+ export declare function createGatewayClient(): TreeseedGatewayClient;
6
+ export declare function createQueueClient(): CloudflareQueuePullClient;
7
+ export declare function resolveManagerConfig(): {
8
+ host: string;
9
+ port: number;
10
+ projectId: string;
11
+ defaultCapacityBudget: number;
12
+ };
13
+ export declare function resolveWorkerConfig(): {
14
+ workerId: string;
15
+ batchSize: number;
16
+ visibilityTimeoutMs: number;
17
+ pollIntervalMs: number;
18
+ leaseSeconds: number;
19
+ managerBaseUrl: string;
20
+ };
@@ -0,0 +1,66 @@
1
+ import { AgentSdk } from "@treeseed/sdk/sdk";
2
+ import { TreeseedGatewayClient, CloudflareQueuePullClient } from "@treeseed/sdk/remote";
3
+ function integerFromEnv(name, fallback) {
4
+ const value = process.env[name];
5
+ if (!value) return fallback;
6
+ const parsed = Number.parseInt(value, 10);
7
+ return Number.isFinite(parsed) ? parsed : fallback;
8
+ }
9
+ function resolveServiceRepoRoot() {
10
+ return process.env.TREESEED_AGENT_REPO_ROOT?.trim() || process.cwd();
11
+ }
12
+ function createServiceSdk() {
13
+ return AgentSdk.createLocal({
14
+ repoRoot: resolveServiceRepoRoot(),
15
+ databaseName: process.env.TREESEED_AGENT_D1_DATABASE ?? "karyon-docs-site-data",
16
+ persistTo: process.env.TREESEED_AGENT_D1_PERSIST_TO ?? void 0
17
+ });
18
+ }
19
+ function createGatewayClient() {
20
+ const baseUrl = process.env.TREESEED_GATEWAY_BASE_URL?.trim();
21
+ const bearerToken = process.env.TREESEED_GATEWAY_BEARER_TOKEN?.trim();
22
+ if (!baseUrl || !bearerToken) {
23
+ return null;
24
+ }
25
+ return new TreeseedGatewayClient({ baseUrl, bearerToken });
26
+ }
27
+ function createQueueClient() {
28
+ const accountId = process.env.CLOUDFLARE_ACCOUNT_ID?.trim();
29
+ const queueId = process.env.TREESEED_QUEUE_ID?.trim();
30
+ const token = process.env.TREESEED_QUEUE_PULL_TOKEN?.trim();
31
+ if (!accountId || !queueId || !token) {
32
+ return null;
33
+ }
34
+ return new CloudflareQueuePullClient({
35
+ accountId,
36
+ queueId,
37
+ token,
38
+ apiBaseUrl: process.env.TREESEED_QUEUE_API_BASE_URL?.trim() || void 0
39
+ });
40
+ }
41
+ function resolveManagerConfig() {
42
+ return {
43
+ host: process.env.HOST?.trim() || "0.0.0.0",
44
+ port: integerFromEnv("PORT", 3100),
45
+ projectId: process.env.TREESEED_PROJECT_ID?.trim() || "treeseed-market",
46
+ defaultCapacityBudget: integerFromEnv("TREESEED_WORKDAY_CAPACITY_BUDGET", 100)
47
+ };
48
+ }
49
+ function resolveWorkerConfig() {
50
+ return {
51
+ workerId: process.env.TREESEED_WORKER_ID?.trim() || `worker-${process.pid}`,
52
+ batchSize: integerFromEnv("TREESEED_QUEUE_BATCH_SIZE", 1),
53
+ visibilityTimeoutMs: integerFromEnv("TREESEED_QUEUE_VISIBILITY_TIMEOUT_MS", 12e4),
54
+ pollIntervalMs: integerFromEnv("TREESEED_WORKER_POLL_INTERVAL_MS", 5e3),
55
+ leaseSeconds: integerFromEnv("TREESEED_TASK_LEASE_SECONDS", 120),
56
+ managerBaseUrl: process.env.TREESEED_MANAGER_BASE_URL?.trim() || `http://${process.env.TREESEED_MANAGER_HOST?.trim() || "manager.railway.internal"}:${integerFromEnv("TREESEED_MANAGER_PORT", 3100)}`
57
+ };
58
+ }
59
+ export {
60
+ createGatewayClient,
61
+ createQueueClient,
62
+ createServiceSdk,
63
+ resolveManagerConfig,
64
+ resolveServiceRepoRoot,
65
+ resolveWorkerConfig
66
+ };
@@ -0,0 +1,4 @@
1
+ export { createManagerApp } from './manager.ts';
2
+ export { runWorkerCycle, startWorkerLoop } from './worker.ts';
3
+ export { runWorkdayStart } from './workday-start.ts';
4
+ export { runWorkdayReport } from './workday-report.ts';
@@ -0,0 +1,11 @@
1
+ import { createManagerApp } from "./manager.js";
2
+ import { runWorkerCycle, startWorkerLoop } from "./worker.js";
3
+ import { runWorkdayStart } from "./workday-start.js";
4
+ import { runWorkdayReport } from "./workday-report.js";
5
+ export {
6
+ createManagerApp,
7
+ runWorkdayReport,
8
+ runWorkdayStart,
9
+ runWorkerCycle,
10
+ startWorkerLoop
11
+ };
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env node
2
+ import { Hono } from 'hono';
3
+ import { AgentSdk } from '@treeseed/sdk/sdk';
4
+ export declare function createManagerApp(sdk?: AgentSdk): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
@@ -0,0 +1,199 @@
1
+ #!/usr/bin/env node
2
+ import { createServer } from "node:http";
3
+ import { Readable } from "node:stream";
4
+ import { fileURLToPath } from "node:url";
5
+ import { Hono } from "hono";
6
+ import { AgentSdk } from "@treeseed/sdk/sdk";
7
+ import { createServiceSdk, resolveManagerConfig } from "./common.js";
8
+ async function honoNodeHandler(app, request, response) {
9
+ const origin = request.headers.host ? `http://${request.headers.host}` : "http://127.0.0.1";
10
+ const url = new URL(request.url ?? "/", origin);
11
+ const webRequest = new Request(url, {
12
+ method: request.method,
13
+ headers: request.headers,
14
+ body: request.method !== "GET" && request.method !== "HEAD" ? request : void 0,
15
+ duplex: "half"
16
+ });
17
+ const webResponse = await app.fetch(webRequest);
18
+ response.statusCode = webResponse.status;
19
+ webResponse.headers.forEach((value, key) => response.setHeader(key, value));
20
+ if (!webResponse.body) {
21
+ response.end();
22
+ return;
23
+ }
24
+ Readable.fromWeb(webResponse.body).pipe(response);
25
+ }
26
+ async function seedRootTasks(sdk, workDayId) {
27
+ const specs = await sdk.listAgentSpecs({ enabled: true });
28
+ const created = [];
29
+ for (const spec of specs) {
30
+ const hasStartTrigger = spec.triggers.some((trigger) => trigger.type === "startup" || trigger.type === "schedule");
31
+ if (!hasStartTrigger) continue;
32
+ created.push(await sdk.createTask({
33
+ workDayId,
34
+ agentId: spec.slug,
35
+ type: "agent_root",
36
+ priority: 100,
37
+ idempotencyKey: `${workDayId}:${spec.slug}:root`,
38
+ payload: {
39
+ agentSlug: spec.slug,
40
+ handler: spec.handler,
41
+ triggerKinds: spec.triggers.map((entry) => entry.type)
42
+ },
43
+ graphVersion: null,
44
+ actor: "manager"
45
+ }));
46
+ }
47
+ return created;
48
+ }
49
+ function createManagerApp(sdk = createServiceSdk()) {
50
+ const config = resolveManagerConfig();
51
+ const app = new Hono();
52
+ app.get("/internal/healthz", (c) => c.json({ ok: true, service: "manager" }));
53
+ app.post("/internal/workdays/start", async (c) => {
54
+ const body = await c.req.json().catch(() => ({}));
55
+ const graphRefresh = await sdk.refreshGraph();
56
+ const workDay = await sdk.startWorkDay({
57
+ id: typeof body.id === "string" ? body.id : void 0,
58
+ projectId: config.projectId,
59
+ capacityBudget: Number(body.capacityBudget ?? config.defaultCapacityBudget),
60
+ graphVersion: graphRefresh.snapshotRoot,
61
+ summary: { graphRefresh },
62
+ actor: "manager"
63
+ });
64
+ const tasks = workDay.payload ? await seedRootTasks(sdk, String(workDay.payload.id)) : [];
65
+ return c.json({
66
+ ok: true,
67
+ workDay: workDay.payload,
68
+ seededTasks: tasks.map((entry) => entry.payload).filter(Boolean)
69
+ });
70
+ });
71
+ app.post("/internal/workdays/:id/close", async (c) => {
72
+ const body = await c.req.json().catch(() => ({}));
73
+ const result = await sdk.closeWorkDay({
74
+ id: c.req.param("id"),
75
+ state: body.state,
76
+ summary: body.summary ?? null,
77
+ actor: "manager"
78
+ });
79
+ return c.json({ ok: true, payload: result.payload });
80
+ });
81
+ app.post("/internal/context/resolve-task", async (c) => {
82
+ const body = await c.req.json().catch(() => ({}));
83
+ const taskId = String(body.taskId ?? "");
84
+ const context = await sdk.getManagerContext(taskId);
85
+ const task = context.payload.task;
86
+ const agent = task ? (await sdk.get({ model: "agent", slug: String(task.agentId) })).payload : null;
87
+ return c.json({
88
+ ok: true,
89
+ payload: {
90
+ ...context.payload,
91
+ agent
92
+ }
93
+ });
94
+ });
95
+ app.post("/internal/graph/search", async (c) => {
96
+ const body = await c.req.json().catch(() => ({}));
97
+ const query = String(body.query ?? "");
98
+ const scope = String(body.scope ?? "sections");
99
+ const payload = scope === "files" ? await sdk.searchFiles(query, body.options) : scope === "entities" ? await sdk.searchEntities(query, body.options) : await sdk.searchSections(query, body.options);
100
+ return c.json({ ok: true, payload });
101
+ });
102
+ app.post("/internal/graph/subgraph", async (c) => {
103
+ const body = await c.req.json().catch(() => ({}));
104
+ const payload = await sdk.getSubgraph(
105
+ Array.isArray(body.seedIds) ? body.seedIds.map(String) : [],
106
+ body.options
107
+ );
108
+ return c.json({ ok: true, payload });
109
+ });
110
+ app.post("/internal/graph/query", async (c) => {
111
+ const body = await c.req.json().catch(() => ({}));
112
+ const payload = await sdk.queryGraph(body);
113
+ if (typeof body.workDayId === "string" && body.workDayId) {
114
+ await sdk.create({
115
+ model: "graph_run",
116
+ data: {
117
+ workDayId: body.workDayId,
118
+ corpusHash: String(body.corpusHash ?? "query-graph"),
119
+ graphVersion: String(body.graphVersion ?? ""),
120
+ queryJson: JSON.stringify(body ?? {}),
121
+ seedIdsJson: JSON.stringify(payload.seedIds),
122
+ selectedNodeIdsJson: JSON.stringify(payload.nodes.map((entry) => entry.node.id)),
123
+ statsJson: JSON.stringify({ nodeCount: payload.nodes.length, edgeCount: payload.edges.length })
124
+ },
125
+ actor: "manager"
126
+ });
127
+ }
128
+ return c.json({ ok: true, payload });
129
+ });
130
+ app.post("/internal/graph/context-pack", async (c) => {
131
+ const body = await c.req.json().catch(() => ({}));
132
+ const payload = await sdk.buildContextPack(body);
133
+ if (typeof body.workDayId === "string" && body.workDayId) {
134
+ await sdk.create({
135
+ model: "graph_run",
136
+ data: {
137
+ workDayId: body.workDayId,
138
+ corpusHash: String(body.corpusHash ?? "context-pack"),
139
+ graphVersion: String(body.graphVersion ?? ""),
140
+ queryJson: JSON.stringify(body ?? {}),
141
+ seedIdsJson: JSON.stringify(payload.seedIds),
142
+ selectedNodeIdsJson: JSON.stringify(payload.includedNodeIds),
143
+ statsJson: JSON.stringify({ nodeCount: payload.nodes.length, edgeCount: payload.edges.length, totalTokenEstimate: payload.totalTokenEstimate })
144
+ },
145
+ actor: "manager"
146
+ });
147
+ }
148
+ return c.json({ ok: true, payload });
149
+ });
150
+ app.post("/internal/graph/parse-dsl", async (c) => {
151
+ const body = await c.req.json().catch(() => ({}));
152
+ const payload = await sdk.parseGraphDsl(String(body.source ?? body.query ?? ""));
153
+ return c.json({ ok: true, payload });
154
+ });
155
+ app.get("/internal/graph/node/:id", async (c) => {
156
+ const payload = await sdk.getGraphNode(c.req.param("id"));
157
+ return payload ? c.json({ ok: true, payload }) : c.json({ ok: false, error: "Unknown graph node." }, 404);
158
+ });
159
+ app.post("/internal/tasks/:id/followups", async (c) => {
160
+ const body = await c.req.json().catch(() => ({}));
161
+ const current = await sdk.get({ model: "task", id: c.req.param("id") });
162
+ if (!current.payload) {
163
+ return c.json({ ok: false, error: "Unknown task." }, 404);
164
+ }
165
+ const followups = Array.isArray(body.followups) ? body.followups : [];
166
+ const created = [];
167
+ for (const followup of followups) {
168
+ created.push(await sdk.createTask({
169
+ workDayId: String(current.payload.workDayId ?? ""),
170
+ agentId: String(followup.agentId ?? current.payload.agentId ?? ""),
171
+ type: String(followup.type ?? "followup"),
172
+ priority: Number(followup.priority ?? 0),
173
+ idempotencyKey: String(followup.idempotencyKey ?? `${c.req.param("id")}:${created.length}`),
174
+ payload: followup.payload ?? {},
175
+ graphVersion: typeof followup.graphVersion === "string" ? followup.graphVersion : null,
176
+ parentTaskId: c.req.param("id"),
177
+ actor: "manager"
178
+ }));
179
+ }
180
+ return c.json({ ok: true, payload: created.map((entry) => entry.payload) });
181
+ });
182
+ return app;
183
+ }
184
+ const currentFile = fileURLToPath(import.meta.url);
185
+ const entryFile = process.argv[1] ?? "";
186
+ if (entryFile === currentFile) {
187
+ const config = resolveManagerConfig();
188
+ const app = createManagerApp();
189
+ const server = createServer((req, res) => {
190
+ void honoNodeHandler(app, req, res);
191
+ });
192
+ server.listen(config.port, config.host, () => {
193
+ process.stdout.write(`Treeseed manager listening on http://${config.host}:${config.port}
194
+ `);
195
+ });
196
+ }
197
+ export {
198
+ createManagerApp
199
+ };
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ export declare function runWorkdayReport(): Promise<{
3
+ ok: boolean;
4
+ skipped: boolean;
5
+ workDayId?: undefined;
6
+ summary?: undefined;
7
+ } | {
8
+ ok: boolean;
9
+ workDayId: string;
10
+ summary: {
11
+ totalTasks: number;
12
+ completedTasks: number;
13
+ failedTasks: number;
14
+ pendingTasks: number;
15
+ };
16
+ skipped?: undefined;
17
+ }>;
@@ -0,0 +1,44 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from "node:url";
3
+ import { createGatewayClient, createServiceSdk } from "./common.js";
4
+ async function runWorkdayReport() {
5
+ const sdk = createServiceSdk();
6
+ const gateway = createGatewayClient();
7
+ const workDays = await sdk.search({ model: "work_day", limit: 1 });
8
+ const active = workDays.payload[0];
9
+ if (!active || typeof active.id !== "string") {
10
+ return { ok: true, skipped: true };
11
+ }
12
+ const tasks = await sdk.searchTasks({ workDayId: active.id, limit: 200 });
13
+ const summary = {
14
+ totalTasks: tasks.payload.length,
15
+ completedTasks: tasks.payload.filter((entry) => entry.state === "completed").length,
16
+ failedTasks: tasks.payload.filter((entry) => entry.state === "failed").length,
17
+ pendingTasks: tasks.payload.filter((entry) => entry.state !== "completed" && entry.state !== "failed").length
18
+ };
19
+ if (gateway) {
20
+ await gateway.requestJson("/reports", {
21
+ body: {
22
+ workDayId: active.id,
23
+ kind: "workday_summary",
24
+ body: summary
25
+ }
26
+ });
27
+ await gateway.requestJson(`/workdays/${encodeURIComponent(active.id)}/close`, {
28
+ body: {
29
+ state: "completed",
30
+ summary
31
+ }
32
+ });
33
+ }
34
+ return { ok: true, workDayId: active.id, summary };
35
+ }
36
+ const currentFile = fileURLToPath(import.meta.url);
37
+ const entryFile = process.argv[1] ?? "";
38
+ if (entryFile === currentFile) {
39
+ process.stdout.write(`${JSON.stringify(await runWorkdayReport(), null, 2)}
40
+ `);
41
+ }
42
+ export {
43
+ runWorkdayReport
44
+ };
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export declare function runWorkdayStart(): Promise<any>;
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env node
2
+ import { fileURLToPath } from "node:url";
3
+ import { resolveWorkerConfig } from "./common.js";
4
+ async function runWorkdayStart() {
5
+ const managerBaseUrl = resolveWorkerConfig().managerBaseUrl;
6
+ const response = await fetch(`${managerBaseUrl}/internal/workdays/start`, {
7
+ method: "POST",
8
+ headers: {
9
+ accept: "application/json",
10
+ "content-type": "application/json"
11
+ },
12
+ body: JSON.stringify({})
13
+ });
14
+ if (!response.ok) {
15
+ throw new Error(`Workday start failed with ${response.status}.`);
16
+ }
17
+ return response.json();
18
+ }
19
+ const currentFile = fileURLToPath(import.meta.url);
20
+ const entryFile = process.argv[1] ?? "";
21
+ if (entryFile === currentFile) {
22
+ process.stdout.write(`${JSON.stringify(await runWorkdayStart(), null, 2)}
23
+ `);
24
+ }
25
+ export {
26
+ runWorkdayStart
27
+ };
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ export declare function runWorkerCycle(): Promise<{
3
+ ok: boolean;
4
+ processed: number;
5
+ }>;
6
+ export declare function startWorkerLoop(): Promise<void>;