@tiangong-ai/cli 0.0.19 → 0.0.20

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 (43) hide show
  1. package/AGENTS.md +8 -2
  2. package/README.md +72 -4
  3. package/dist/cli.js +2 -0
  4. package/dist/cli.js.map +1 -1
  5. package/dist/research/commands.js +6 -0
  6. package/dist/research/commands.js.map +1 -1
  7. package/dist/research/orchestration.d.ts +3 -0
  8. package/dist/research/orchestration.js +236 -0
  9. package/dist/research/orchestration.js.map +1 -0
  10. package/dist/research/workspace/broker.d.ts +5 -0
  11. package/dist/research/workspace/broker.js +353 -0
  12. package/dist/research/workspace/broker.js.map +1 -0
  13. package/dist/research/workspace/capabilities.d.ts +10 -0
  14. package/dist/research/workspace/capabilities.js +291 -0
  15. package/dist/research/workspace/capabilities.js.map +1 -0
  16. package/dist/research/workspace/constants.d.ts +8 -0
  17. package/dist/research/workspace/constants.js +37 -0
  18. package/dist/research/workspace/constants.js.map +1 -0
  19. package/dist/research/workspace/context.d.ts +3 -0
  20. package/dist/research/workspace/context.js +77 -0
  21. package/dist/research/workspace/context.js.map +1 -0
  22. package/dist/research/workspace/executor.d.ts +12 -0
  23. package/dist/research/workspace/executor.js +353 -0
  24. package/dist/research/workspace/executor.js.map +1 -0
  25. package/dist/research/workspace/journal.d.ts +7 -0
  26. package/dist/research/workspace/journal.js +104 -0
  27. package/dist/research/workspace/journal.js.map +1 -0
  28. package/dist/research/workspace/projects.d.ts +9 -0
  29. package/dist/research/workspace/projects.js +230 -0
  30. package/dist/research/workspace/projects.js.map +1 -0
  31. package/dist/research/workspace/runtime.d.ts +27 -0
  32. package/dist/research/workspace/runtime.js +519 -0
  33. package/dist/research/workspace/runtime.js.map +1 -0
  34. package/dist/research/workspace/storage.d.ts +25 -0
  35. package/dist/research/workspace/storage.js +218 -0
  36. package/dist/research/workspace/storage.js.map +1 -0
  37. package/dist/research/workspace/types.d.ts +181 -0
  38. package/dist/research/workspace/types.js +2 -0
  39. package/dist/research/workspace/types.js.map +1 -0
  40. package/dist/research/workspace/workspace.d.ts +12 -0
  41. package/dist/research/workspace/workspace.js +340 -0
  42. package/dist/research/workspace/workspace.js.map +1 -0
  43. package/package.json +3 -2
@@ -0,0 +1,230 @@
1
+ import { randomUUID } from "node:crypto";
2
+ import { lstat, readdir } from "node:fs/promises";
3
+ import { basename, join, resolve, sep } from "node:path";
4
+ import { CliError } from "../../errors.js";
5
+ import { RESEARCH_CONTROL_DIRECTORY } from "./constants.js";
6
+ import { appendJournalEvent } from "./journal.js";
7
+ import { ensureDirectory, fileSize, readJsonFile, sha256File, workspacePaths, writeJsonAtomic, } from "./storage.js";
8
+ import { loadWorkspaceConfig, withWorkspaceLock } from "./workspace.js";
9
+ const PROJECT_ID_PATTERN = /^[a-z0-9][a-z0-9-]{2,63}$/;
10
+ export async function initializeProject(root, projectId, question) {
11
+ validateProjectId(projectId);
12
+ const normalizedQuestion = question.trim();
13
+ if (normalizedQuestion.length < 8 || normalizedQuestion.length > 4000) {
14
+ throw new CliError("Research question must contain 8-4000 characters.", {
15
+ code: "RESEARCH_QUESTION_INVALID",
16
+ exitCode: 2,
17
+ });
18
+ }
19
+ return withWorkspaceLock(root, "project.init", async () => {
20
+ const paths = workspacePaths(root);
21
+ const projectRoot = join(paths.projects, projectId);
22
+ const projectPath = join(projectRoot, "project.json");
23
+ const existing = await lstat(projectRoot).catch(() => undefined);
24
+ if (existing) {
25
+ throw new CliError(`Research project already exists: ${projectId}`, {
26
+ code: "RESEARCH_PROJECT_EXISTS",
27
+ exitCode: 2,
28
+ });
29
+ }
30
+ const config = await loadWorkspaceConfig(root);
31
+ const now = new Date().toISOString();
32
+ const project = {
33
+ schemaVersion: 1,
34
+ id: projectId,
35
+ question: normalizedQuestion,
36
+ status: "ready",
37
+ createdAt: now,
38
+ updatedAt: now,
39
+ inputs: [],
40
+ packages: defaultWorkPackages(config),
41
+ usage: { tokens: 0, costUsd: 0, wallSeconds: 0 },
42
+ };
43
+ await Promise.all([
44
+ ensureDirectory(projectRoot),
45
+ ensureDirectory(join(projectRoot, "outputs")),
46
+ ensureDirectory(join(projectRoot, "runs")),
47
+ ]);
48
+ await writeJsonAtomic(projectPath, project);
49
+ await appendJournalEvent(paths.journal, "project.initialized", projectId, {
50
+ projectId,
51
+ questionSha256: await hashQuestion(normalizedQuestion),
52
+ });
53
+ return project;
54
+ });
55
+ }
56
+ export async function addProjectInput(root, projectId, inputPath, role) {
57
+ validateProjectId(projectId);
58
+ const canonicalInput = resolve(inputPath);
59
+ if (canonicalInput !== inputPath) {
60
+ throw new CliError(`Input path must be absolute: ${inputPath}`, {
61
+ code: "RESEARCH_INPUT_INVALID",
62
+ exitCode: 2,
63
+ });
64
+ }
65
+ if (canonicalInput.split(sep).includes(RESEARCH_CONTROL_DIRECTORY)) {
66
+ throw new CliError("Research inputs cannot come from a research control directory.", {
67
+ code: "RESEARCH_INPUT_INVALID",
68
+ exitCode: 2,
69
+ });
70
+ }
71
+ const info = await lstat(canonicalInput).catch(() => undefined);
72
+ if (!info?.isFile() || info.isSymbolicLink()) {
73
+ throw new CliError(`Research input must be a regular file: ${inputPath}`, {
74
+ code: "RESEARCH_INPUT_INVALID",
75
+ exitCode: 2,
76
+ });
77
+ }
78
+ return withWorkspaceLock(root, "project.input.add", async () => {
79
+ const project = await loadProject(root, projectId);
80
+ const sha256 = await sha256File(canonicalInput);
81
+ const existing = project.inputs.find((input) => input.sha256 === sha256 && input.role === role);
82
+ if (existing)
83
+ return existing;
84
+ const input = {
85
+ id: `${slug(basename(canonicalInput))}-${sha256.slice(0, 12)}`,
86
+ role,
87
+ path: canonicalInput,
88
+ sha256,
89
+ bytes: await fileSize(canonicalInput),
90
+ addedAt: new Date().toISOString(),
91
+ };
92
+ project.inputs.push(input);
93
+ project.inputs.sort((left, right) => left.id.localeCompare(right.id));
94
+ project.updatedAt = new Date().toISOString();
95
+ await saveProject(root, project);
96
+ await appendJournalEvent(workspacePaths(root).journal, "project.input.added", projectId, {
97
+ projectId,
98
+ inputId: input.id,
99
+ role,
100
+ sha256,
101
+ bytes: input.bytes,
102
+ });
103
+ return input;
104
+ });
105
+ }
106
+ export async function loadProject(root, projectId) {
107
+ validateProjectId(projectId);
108
+ const project = await readJsonFile(join(workspacePaths(root).projects, projectId, "project.json"), `Research project ${projectId}`);
109
+ validateProjectShape(project, projectId);
110
+ return project;
111
+ }
112
+ export async function listProjects(root) {
113
+ const entries = await readdir(workspacePaths(root).projects, { withFileTypes: true });
114
+ const projects = [];
115
+ for (const entry of entries.sort((left, right) => left.name.localeCompare(right.name))) {
116
+ if (!entry.isDirectory() || entry.isSymbolicLink())
117
+ continue;
118
+ projects.push(await loadProject(root, entry.name));
119
+ }
120
+ return projects;
121
+ }
122
+ export async function saveProject(root, project) {
123
+ validateProjectShape(project, project.id);
124
+ await writeJsonAtomic(join(workspacePaths(root).projects, project.id, "project.json"), project);
125
+ }
126
+ export function refreshProject(project) {
127
+ for (const workPackage of project.packages) {
128
+ if (workPackage.status !== "pending" && workPackage.status !== "retry")
129
+ continue;
130
+ const dependenciesComplete = workPackage.dependencies.every((dependency) => project.packages.find((candidate) => candidate.id === dependency)?.status === "complete");
131
+ if (dependenciesComplete)
132
+ workPackage.status = "ready";
133
+ }
134
+ if (project.packages.some((item) => item.status === "failed"))
135
+ project.status = "blocked";
136
+ else if (project.packages.every((item) => item.status === "complete"))
137
+ project.status = "complete";
138
+ else if (project.packages.some((item) => item.status === "running"))
139
+ project.status = "running";
140
+ else
141
+ project.status = "ready";
142
+ project.updatedAt = new Date().toISOString();
143
+ return project;
144
+ }
145
+ export function nextReadyPackage(project) {
146
+ refreshProject(project);
147
+ return project.packages.find((workPackage) => workPackage.status === "ready");
148
+ }
149
+ export function packageById(project, packageId) {
150
+ const workPackage = project.packages.find((candidate) => candidate.id === packageId);
151
+ if (!workPackage) {
152
+ throw new CliError(`Unknown work package ${packageId} in project ${project.id}.`, {
153
+ code: "RESEARCH_PACKAGE_INVALID",
154
+ exitCode: 2,
155
+ });
156
+ }
157
+ return workPackage;
158
+ }
159
+ function defaultWorkPackages(config) {
160
+ const maxAttempts = config.budget.maxAttemptsPerPackage;
161
+ return [
162
+ workPackage("discover", "discover", "agent", "producer", [], ["outputs/evidence.json"], maxAttempts),
163
+ workPackage("analyze", "analyze", "agent", "producer", ["discover"], ["outputs/analysis.json"], maxAttempts),
164
+ workPackage("synthesize", "synthesize", "agent", "producer", ["analyze"], ["outputs/report.md"], maxAttempts),
165
+ workPackage("review", "review", "agent", "reviewer", ["synthesize"], ["outputs/review.json"], maxAttempts),
166
+ workPackage("close", "close", "verify", "mechanical", ["review"], ["outputs/closure.json"], 1),
167
+ ];
168
+ }
169
+ function workPackage(id, stage, kind, executor, dependencies, expectedOutputs, maxAttempts) {
170
+ return {
171
+ id,
172
+ stage,
173
+ kind,
174
+ executor,
175
+ dependencies,
176
+ expectedOutputs,
177
+ status: dependencies.length ? "pending" : "ready",
178
+ attempts: 0,
179
+ maxAttempts,
180
+ lastError: null,
181
+ startedAt: null,
182
+ completedAt: null,
183
+ };
184
+ }
185
+ function validateProjectShape(project, expectedId) {
186
+ if (project.schemaVersion !== 1 ||
187
+ project.id !== expectedId ||
188
+ !PROJECT_ID_PATTERN.test(project.id) ||
189
+ typeof project.question !== "string" ||
190
+ !Array.isArray(project.inputs) ||
191
+ !Array.isArray(project.packages) ||
192
+ !project.usage ||
193
+ typeof project.usage.tokens !== "number" ||
194
+ typeof project.usage.costUsd !== "number" ||
195
+ typeof project.usage.wallSeconds !== "number") {
196
+ throw new CliError(`Research project state is invalid: ${expectedId}`, {
197
+ code: "RESEARCH_PROJECT_INVALID",
198
+ exitCode: 2,
199
+ });
200
+ }
201
+ const packageIds = new Set(project.packages.map((item) => item.id));
202
+ if (packageIds.size !== project.packages.length ||
203
+ project.packages.some((item) => !["agent", "verify"].includes(item.kind) ||
204
+ !["producer", "reviewer", "mechanical"].includes(item.executor) ||
205
+ item.dependencies.some((dependency) => !packageIds.has(dependency)) ||
206
+ item.expectedOutputs.some((path) => !path.startsWith("outputs/")))) {
207
+ throw new CliError(`Research project work packages are invalid: ${expectedId}`, {
208
+ code: "RESEARCH_PROJECT_INVALID",
209
+ exitCode: 2,
210
+ });
211
+ }
212
+ }
213
+ function validateProjectId(projectId) {
214
+ if (!PROJECT_ID_PATTERN.test(projectId)) {
215
+ throw new CliError("Project ID must contain 3-64 lowercase letters, digits, or hyphens and start with a letter or digit.", { code: "RESEARCH_PROJECT_ID_INVALID", exitCode: 2 });
216
+ }
217
+ }
218
+ function slug(value) {
219
+ const result = value
220
+ .toLowerCase()
221
+ .replace(/[^a-z0-9]+/g, "-")
222
+ .replace(/^-|-$/g, "")
223
+ .slice(0, 40);
224
+ return result || randomUUID().slice(0, 8);
225
+ }
226
+ async function hashQuestion(question) {
227
+ const { createHash } = await import("node:crypto");
228
+ return createHash("sha256").update(question, "utf8").digest("hex");
229
+ }
230
+ //# sourceMappingURL=projects.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"projects.js","sourceRoot":"","sources":["../../../src/research/workspace/projects.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import { type AgentExecutionRequest } from "./executor.js";
2
+ import type { ExecutionResult, ProjectState } from "./types.js";
3
+ export interface RunOptions {
4
+ maxParallel: number;
5
+ maxCycles: number;
6
+ dryRun: boolean;
7
+ environment: NodeJS.ProcessEnv;
8
+ }
9
+ export type PackageExecutor = (request: AgentExecutionRequest) => Promise<ExecutionResult>;
10
+ export interface WorkspaceRunResult {
11
+ workspace: string;
12
+ status: "complete" | "blocked" | "ready" | "dry-run";
13
+ stopReason: "dry-run" | "all-projects-complete" | "project-blocked" | "cycle-limit" | "no-ready-work" | "no-projects";
14
+ cycles: number;
15
+ executed: Array<{
16
+ projectId: string;
17
+ packageId: string;
18
+ status: string;
19
+ }>;
20
+ projects: Array<{
21
+ id: string;
22
+ status: ProjectState["status"];
23
+ readyPackage: string | null;
24
+ usage: ProjectState["usage"];
25
+ }>;
26
+ }
27
+ export declare function runResearchWorkspace(root: string, options: RunOptions, packageExecutor?: PackageExecutor): Promise<WorkspaceRunResult>;