academic-army 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/.editorconfig +9 -0
  2. package/.github/workflows/publish.yml +44 -0
  3. package/.prettierrc.json +3 -0
  4. package/LICENSE +21 -0
  5. package/README.md +172 -0
  6. package/README.zh-CN.md +172 -0
  7. package/agent-forge.yaml +83 -0
  8. package/eslint.config.js +28 -0
  9. package/install_mcp.py +85 -0
  10. package/mcp-server/__main__.py +33 -0
  11. package/mcp-server/deepresearch/__init__.py +3 -0
  12. package/mcp-server/deepresearch/tools.py +33 -0
  13. package/mcp-server/requirements.txt +4 -0
  14. package/metaskills/README.md +131 -0
  15. package/metaskills/README.zh-CN.md +131 -0
  16. package/metaskills/academic-army-architect/METASKILL.md +91 -0
  17. package/metaskills/academic-army-architect/envolve.sh +9 -0
  18. package/metaskills/academic-army-coding-plan/ENVOLVETASK.md +1 -0
  19. package/metaskills/academic-army-coding-plan/METASKILL.md +118 -0
  20. package/metaskills/academic-army-coding-plan/envolve.sh +9 -0
  21. package/metaskills/academic-army-coding-style/METASKILL.md +292 -0
  22. package/metaskills/academic-army-experiment-plan/ENVOLVETASK.md +1 -0
  23. package/metaskills/academic-army-experiment-plan/METASKILL.md +82 -0
  24. package/metaskills/academic-army-experiment-plan/envolve.sh +9 -0
  25. package/metaskills/academic-army-repo-scaffold/ENVOLVETASK.md +1 -0
  26. package/metaskills/academic-army-repo-scaffold/METASKILL.md +223 -0
  27. package/metaskills/academic-army-repo-scaffold/envolve.sh +9 -0
  28. package/package.json +35 -0
  29. package/runs/develop-skill.sh +17 -0
  30. package/runs/develop.sh +16 -0
  31. package/skills/academic-army-architect/SKILL.md +336 -0
  32. package/skills/academic-army-architect/agents/openai.yaml +11 -0
  33. package/skills/academic-army-architect/references/blueprint-schema.md +345 -0
  34. package/skills/academic-army-coding-plan/SKILL.md +491 -0
  35. package/skills/academic-army-coding-plan/agents/openai.yaml +11 -0
  36. package/skills/academic-army-coding-style/SKILL.md +915 -0
  37. package/skills/academic-army-coding-style/agents/openai.yaml +11 -0
  38. package/skills/academic-army-experiment-plan/SKILL.md +517 -0
  39. package/skills/academic-army-experiment-plan/agents/openai.yaml +11 -0
  40. package/skills/academic-army-repo-scaffold/SKILL.md +756 -0
  41. package/skills/academic-army-repo-scaffold/agents/openai.yaml +10 -0
  42. package/src/README.md +79 -0
  43. package/src/README.zh-CN.md +79 -0
  44. package/src/cli.ts +55 -0
  45. package/src/developing/README.md +146 -0
  46. package/src/developing/README.zh-CN.md +146 -0
  47. package/src/developing/agents/developer.ts +40 -0
  48. package/src/developing/agents/factory.ts +11 -0
  49. package/src/developing/agents/index.ts +8 -0
  50. package/src/developing/agents/manager.ts +74 -0
  51. package/src/developing/agents/prompts.ts +12 -0
  52. package/src/developing/agents/reviewer.ts +44 -0
  53. package/src/developing/agents/trajectory-optimizer.ts +70 -0
  54. package/src/developing/agents/types.ts +41 -0
  55. package/src/developing/index.ts +2 -0
  56. package/src/developing/pipeline.ts +306 -0
  57. package/src/developing/pipelineskill.ts +169 -0
  58. package/src/evolve-skill/README.md +116 -0
  59. package/src/evolve-skill/README.zh-CN.md +116 -0
  60. package/src/evolve-skill/agents/evaluator.ts +28 -0
  61. package/src/evolve-skill/agents/factory.ts +11 -0
  62. package/src/evolve-skill/agents/index.ts +4 -0
  63. package/src/evolve-skill/agents/modifier.ts +27 -0
  64. package/src/evolve-skill/agents/runner.ts +19 -0
  65. package/src/evolve-skill/index.ts +1 -0
  66. package/src/evolve-skill/pipeline.ts +140 -0
  67. package/src/pipeline.ts +65 -0
  68. package/tsconfig.json +22 -0
@@ -0,0 +1,12 @@
1
+ export function codingStyleSkillInstruction(codingStyleSkillPath: string): string {
2
+ return `Load and follow the skill at ${codingStyleSkillPath}. It describes how to keep repository code concise, readable, low-friction, and easy to modify.`;
3
+ }
4
+
5
+ export function goalInstruction(goal: string): string {
6
+ return `
7
+ Current goal:
8
+ ${goal}
9
+
10
+ Use this goal as the current high-level objective.
11
+ `;
12
+ }
@@ -0,0 +1,44 @@
1
+ import { codingStyleSkillInstruction } from "./prompts.js";
2
+ import { DevelopingAgent, type DevelopingAgentVariables } from "./types.js";
3
+
4
+ export type CodeReviewerVariables = DevelopingAgentVariables & {
5
+ acceptMark: string;
6
+ currentTask: string;
7
+ developerReport: string;
8
+ };
9
+
10
+ export class CodeReviewerAgent extends DevelopingAgent<CodeReviewerVariables> {
11
+ protected buildPrompt(variables: Readonly<CodeReviewerVariables>): string {
12
+ const codingStyleSkillPath = this.workspaceRelativePath(variables.codingStyleSkillPath);
13
+ const targetPath = this.workspaceRelativePath(variables.targetPath);
14
+ const paperBlueprintPath = this.workspaceRelativePath(variables.paperBlueprintPath);
15
+ const experimentPlanPath = this.workspaceRelativePath(variables.experimentPlanPath);
16
+ const codingPlanPath = this.workspaceRelativePath(variables.codingPlanPath);
17
+ const codingStyleSkillInstructionText = codingStyleSkillInstruction(codingStyleSkillPath);
18
+
19
+ return (
20
+ codingStyleSkillInstructionText +
21
+ `
22
+
23
+ Review the current developer task result. Read only.
24
+
25
+ Read:
26
+ - target repository: ${targetPath}
27
+ - paper blueprint: ${paperBlueprintPath}
28
+ - experiment plan: ${experimentPlanPath}
29
+ - coding plan: ${codingPlanPath}
30
+
31
+ Current developer task:
32
+ ${variables.currentTask}
33
+
34
+ Developer report:
35
+ ${variables.developerReport}
36
+
37
+ If the code for the current task is complete and needs no more changes, output exactly:
38
+ ${variables.acceptMark}
39
+
40
+ Otherwise output the revision feedback for the Developer.
41
+ `
42
+ );
43
+ }
44
+ }
@@ -0,0 +1,70 @@
1
+ import { Agent } from "coding-agent-forge/agent";
2
+ import { readFileSync } from "node:fs";
3
+ import type { DevelopingAgentVariables } from "./types.js";
4
+
5
+ type ScanTrajectoryOptimizerVariables = DevelopingAgentVariables & {
6
+ phase: "scan";
7
+ currentTask: string;
8
+ };
9
+
10
+ type OptimizeTrajectoryOptimizerVariables = DevelopingAgentVariables & {
11
+ phase: "optimize";
12
+ currentTask: string;
13
+ revisionReport: string;
14
+ todoUpdateReport: string;
15
+ metaskillPath: string;
16
+ };
17
+
18
+ export type TrajectoryOptimizerVariables =
19
+ | ScanTrajectoryOptimizerVariables
20
+ | OptimizeTrajectoryOptimizerVariables;
21
+
22
+ export class TrajectoryOptimizerAgent extends Agent<TrajectoryOptimizerVariables> {
23
+ protected buildPrompt(variables: Readonly<TrajectoryOptimizerVariables>): string {
24
+ if (variables.phase === "scan") {
25
+ return `
26
+ Read only. Scan the target repository before the Developer starts the current task.
27
+
28
+ Read:
29
+ - skill: ${variables.codingStyleSkillPath}
30
+ - target repository: ${variables.targetPath}
31
+ - paper blueprint: ${variables.paperBlueprintPath}
32
+ - experiment plan: ${variables.experimentPlanPath}
33
+ - coding plan: ${variables.codingPlanPath}
34
+
35
+ Current developer task:
36
+ ${variables.currentTask}
37
+
38
+ Output a concise baseline of the repository state relevant to this task and the main guidance the skill should provide.
39
+ `;
40
+ }
41
+
42
+ const metaskill = readFileSync(variables.metaskillPath, "utf8");
43
+ return `
44
+ Revise the skill at ${variables.codingStyleSkillPath} so it produces better development trajectories.
45
+
46
+ The metaskill below contains the design goals and tips of this skill:
47
+
48
+ ${metaskill}
49
+
50
+ Read:
51
+ - target repository: ${variables.targetPath}
52
+ - paper blueprint: ${variables.paperBlueprintPath}
53
+ - experiment plan: ${variables.experimentPlanPath}
54
+ - coding plan: ${variables.codingPlanPath}
55
+
56
+ Current developer task:
57
+ ${variables.currentTask}
58
+
59
+ Revision report:
60
+ ${variables.revisionReport}
61
+
62
+ TODO update report:
63
+ ${variables.todoUpdateReport}
64
+
65
+ Evaluate whether the skill produced a good modification trajectory, then edit the skill directly. Focus on missing, misleading, or redundant guidance that affected task selection, coding, review, or TODO update.
66
+
67
+ Output a concise optimizer report with the main skill changes.
68
+ `;
69
+ }
70
+ }
@@ -0,0 +1,41 @@
1
+ import type { PromptConstants, Thread } from "coding-agent-forge";
2
+ import { Agent } from "coding-agent-forge/agent";
3
+ import { statSync } from "node:fs";
4
+ import path from "node:path";
5
+
6
+ export type DevelopingAgentVariables = {
7
+ targetPath: string;
8
+ codingStyleSkillPath: string;
9
+ paperBlueprintPath: string;
10
+ experimentPlanPath: string;
11
+ codingPlanPath: string;
12
+ goal: string;
13
+ };
14
+
15
+ export type DevelopingAgentConstants = {
16
+ workspacePath: string;
17
+ };
18
+
19
+ export abstract class DevelopingAgent<Variables extends DevelopingAgentVariables> extends Agent<
20
+ Variables,
21
+ DevelopingAgentConstants
22
+ > {
23
+ protected readonly workspacePath: string;
24
+
25
+ constructor(thread: Thread, constants: Readonly<PromptConstants>) {
26
+ if (!constants.workspacePath) {
27
+ throw new Error("Developing agent constants.workspacePath must be configured.");
28
+ }
29
+
30
+ const workspacePath = path.resolve(constants.workspacePath);
31
+ if (!statSync(workspacePath).isDirectory()) {
32
+ throw new Error(`workspacePath must be a directory: ${workspacePath}`);
33
+ }
34
+ super(thread, { workspacePath });
35
+ this.workspacePath = workspacePath;
36
+ }
37
+
38
+ protected workspaceRelativePath(filePath: string): string {
39
+ return path.relative(this.workspacePath, path.resolve(filePath)) || ".";
40
+ }
41
+ }
@@ -0,0 +1,2 @@
1
+ export * from "./pipeline.js";
2
+ export * from "./pipelineskill.js";
@@ -0,0 +1,306 @@
1
+ import { AgentTeam, type RecordCallback } from "coding-agent-forge";
2
+ import { existsSync } from "node:fs";
3
+ import { cp, mkdir, readFile, writeFile } from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { parseArgs } from "node:util";
6
+ import { definePipeline, type ParsedPipelineArgs } from "../pipeline.js";
7
+ import {
8
+ agentFactories,
9
+ type CodingManagerVariables,
10
+ type CodeReviewerVariables,
11
+ type DeveloperVariables,
12
+ } from "./agents/index.js";
13
+ import type { DevelopingAgentVariables } from "./agents/types.js";
14
+
15
+ export type DevelopingAgentVariablesByName = {
16
+ "coding-manager": CodingManagerVariables;
17
+ developer: DeveloperVariables;
18
+ "code-reviewer": CodeReviewerVariables;
19
+ };
20
+
21
+ export type DevelopingOptions = {
22
+ targetPath: string;
23
+ achiveDir: string;
24
+ artifactPath: string;
25
+ codingStyleSkillPath: string;
26
+ paperBlueprintPath: string;
27
+ experimentPlanPath: string;
28
+ codingPlanPath: string;
29
+ goalPath: string;
30
+ maxIterations: number;
31
+ maxRevisionIterations: number;
32
+ hooks?: DevelopingHooks;
33
+ };
34
+
35
+ export type DevelopingHooks = {
36
+ beforeRevisionLoop?: (
37
+ agentVariables: DevelopingAgentVariables,
38
+ currentTask: string,
39
+ ) => Promise<void> | void;
40
+ afterRevision?: (
41
+ revision: number,
42
+ agentVariables: DevelopingAgentVariables,
43
+ currentTask: string,
44
+ developerReport: string,
45
+ reviewerReport: string,
46
+ revisionReports: readonly string[],
47
+ ) => Promise<void> | void;
48
+ afterTodoUpdate?: (
49
+ agentVariables: DevelopingAgentVariables,
50
+ currentTask: string,
51
+ revisionReport: string,
52
+ todoUpdateReport: string,
53
+ ) => Promise<void> | void;
54
+ };
55
+
56
+ const USAGE = [
57
+ "Usage: npm run developing --",
58
+ "--config <path>",
59
+ "--target-path <folder>",
60
+ "--achive-dir <folder>",
61
+ "--artifact-path <folder>",
62
+ "--coding-style-skill-path <path>",
63
+ "--paper-blueprint-path <path>",
64
+ "--experiment-plan-path <path>",
65
+ "--coding-plan-path <path>",
66
+ "--goal-path <path>",
67
+ "[--max-iterations <positive-integer>]",
68
+ "[--max-revision-iterations <positive-integer>]",
69
+ ].join(" ");
70
+
71
+ const FINISH_MARK = "FINISHED";
72
+ const ACCEPT_MARK = "ACCEPT";
73
+
74
+ export function parseDevelopingArgs(
75
+ args: readonly string[],
76
+ ): ParsedPipelineArgs<DevelopingOptions> {
77
+ const {
78
+ values: {
79
+ config,
80
+ "target-path": targetPath,
81
+ "achive-dir": achiveDir,
82
+ "artifact-path": artifactPath,
83
+ "coding-style-skill-path": codingStyleSkillPath,
84
+ "paper-blueprint-path": paperBlueprintPath,
85
+ "experiment-plan-path": experimentPlanPath,
86
+ "coding-plan-path": codingPlanPath,
87
+ "goal-path": goalPath,
88
+ "max-iterations": maxIterations,
89
+ "max-revision-iterations": maxRevisionIterations,
90
+ },
91
+ } = parseArgs({
92
+ args: [...args],
93
+ options: {
94
+ config: { type: "string", multiple: true },
95
+ "target-path": { type: "string" },
96
+ "achive-dir": { type: "string" },
97
+ "artifact-path": { type: "string" },
98
+ "coding-style-skill-path": { type: "string" },
99
+ "paper-blueprint-path": { type: "string" },
100
+ "experiment-plan-path": { type: "string" },
101
+ "coding-plan-path": { type: "string" },
102
+ "goal-path": { type: "string" },
103
+ "max-iterations": { type: "string" },
104
+ "max-revision-iterations": { type: "string" },
105
+ },
106
+ });
107
+
108
+ if (
109
+ config === undefined ||
110
+ targetPath === undefined ||
111
+ achiveDir === undefined ||
112
+ artifactPath === undefined ||
113
+ codingStyleSkillPath === undefined ||
114
+ paperBlueprintPath === undefined ||
115
+ experimentPlanPath === undefined ||
116
+ codingPlanPath === undefined ||
117
+ goalPath === undefined
118
+ ) {
119
+ throw new Error(USAGE);
120
+ }
121
+
122
+ return {
123
+ configPaths: config,
124
+ runningOptions: {
125
+ targetPath,
126
+ achiveDir,
127
+ artifactPath,
128
+ codingStyleSkillPath,
129
+ paperBlueprintPath,
130
+ experimentPlanPath,
131
+ codingPlanPath,
132
+ goalPath,
133
+ maxIterations: Number(maxIterations ?? 10),
134
+ maxRevisionIterations: Number(maxRevisionIterations ?? 3),
135
+ },
136
+ };
137
+ }
138
+
139
+ export async function developing(
140
+ team: AgentTeam<DevelopingAgentVariablesByName>,
141
+ options: DevelopingOptions,
142
+ ): Promise<void> {
143
+ const logRecord: RecordCallback = (thread, record) => {
144
+ console.log(thread.recordToPrettyString(record));
145
+ };
146
+
147
+ const achiveDir = path.resolve(options.achiveDir);
148
+ const artifactPath = path.resolve(options.artifactPath);
149
+ const todoPath = path.join(artifactPath, "TODO.md");
150
+ const goal = await readGoal(options.goalPath);
151
+ const agentVariables: DevelopingAgentVariables = {
152
+ targetPath: path.resolve(options.targetPath),
153
+ codingStyleSkillPath: path.resolve(options.codingStyleSkillPath),
154
+ paperBlueprintPath: path.resolve(options.paperBlueprintPath),
155
+ experimentPlanPath: path.resolve(options.experimentPlanPath),
156
+ codingPlanPath: path.resolve(options.codingPlanPath),
157
+ goal,
158
+ };
159
+
160
+ await mkdir(achiveDir, { recursive: true });
161
+ await mkdir(artifactPath, { recursive: true });
162
+ if (!existsSync(todoPath)) {
163
+ await writeText(todoPath, "# TODO");
164
+ }
165
+ await mkdir(agentVariables.targetPath, { recursive: true });
166
+
167
+ for (let iteration = 1; iteration <= options.maxIterations; iteration++) {
168
+ console.log(`\n# Developing iteration ${String(iteration)}\n`);
169
+ const archiveDir = path.join(achiveDir, new Date().toISOString().replace(/[:.]/g, "-"));
170
+ await mkdir(archiveDir, { recursive: true });
171
+
172
+ const codingManager = await team.createAgent("coding-manager");
173
+ const developer = await team.createAgent("developer");
174
+ const codeReviewer = await team.createAgent("code-reviewer");
175
+
176
+ const currentTask = (
177
+ await codingManager.runStreamed(
178
+ {
179
+ ...agentVariables,
180
+ todoPath,
181
+ finishMark: FINISH_MARK,
182
+ phase: "select",
183
+ },
184
+ logRecord,
185
+ )
186
+ ).trim();
187
+ await writeText(path.join(archiveDir, "current_task.md"), currentTask);
188
+
189
+ if (currentTask.trim() === FINISH_MARK) {
190
+ console.log(`\n# ${FINISH_MARK}\n`);
191
+ return;
192
+ }
193
+
194
+ let previousReviewerReport = "";
195
+ const revisionReports: string[] = [];
196
+
197
+ await options.hooks?.beforeRevisionLoop?.(agentVariables, currentTask);
198
+
199
+ for (let revision = 1; revision <= options.maxRevisionIterations; revision++) {
200
+ console.log(`\n# Review revision ${String(revision)}\n`);
201
+
202
+ const developerVariables: DeveloperVariables = {
203
+ ...agentVariables,
204
+ currentTask,
205
+ };
206
+ if (previousReviewerReport) {
207
+ developerVariables.reviewerReport = previousReviewerReport;
208
+ }
209
+
210
+ const developerReport = (await developer.runStreamed(developerVariables, logRecord)).trim();
211
+ await writeText(
212
+ path.join(archiveDir, `developer_report_${String(revision).padStart(3, "0")}.md`),
213
+ developerReport,
214
+ );
215
+ revisionReports.push(`Developer report ${String(revision)}:\n${developerReport}`);
216
+
217
+ const reviewerReport = (
218
+ await codeReviewer.runStreamed(
219
+ {
220
+ ...agentVariables,
221
+ acceptMark: ACCEPT_MARK,
222
+ currentTask,
223
+ developerReport,
224
+ },
225
+ logRecord,
226
+ )
227
+ ).trim();
228
+ await writeText(
229
+ path.join(archiveDir, `code_review_${String(revision).padStart(3, "0")}.md`),
230
+ reviewerReport,
231
+ );
232
+ revisionReports.push(`Reviewer report ${String(revision)}:\n${reviewerReport}`);
233
+
234
+ const accepted = reviewerReport.trim() === ACCEPT_MARK;
235
+ if (accepted) {
236
+ revisionReports.push("Reviewer accepted the changes.");
237
+ }
238
+
239
+ if (!accepted && revision === options.maxRevisionIterations) {
240
+ revisionReports.push("Reviewer did not accept the changes before max revision iterations.");
241
+ }
242
+
243
+ await options.hooks?.afterRevision?.(
244
+ revision,
245
+ agentVariables,
246
+ currentTask,
247
+ developerReport,
248
+ reviewerReport,
249
+ revisionReports,
250
+ );
251
+ if (accepted) {
252
+ break;
253
+ }
254
+ previousReviewerReport = reviewerReport;
255
+ }
256
+
257
+ const revisionReport = revisionReports.join("\n\n");
258
+ await writeText(path.join(archiveDir, "revision_report.md"), revisionReport);
259
+
260
+ const todoUpdateReport = (
261
+ await codingManager.runStreamed(
262
+ {
263
+ ...agentVariables,
264
+ todoPath,
265
+ finishMark: FINISH_MARK,
266
+ phase: "update",
267
+ currentTask,
268
+ revisionReport,
269
+ },
270
+ logRecord,
271
+ )
272
+ ).trim();
273
+ await writeText(path.join(archiveDir, "todo_update_report.md"), todoUpdateReport);
274
+ await cp(artifactPath, path.join(archiveDir, "artifacts"), { recursive: true });
275
+
276
+ await options.hooks?.afterTodoUpdate?.(
277
+ agentVariables,
278
+ currentTask,
279
+ revisionReport,
280
+ todoUpdateReport,
281
+ );
282
+ }
283
+
284
+ throw new Error(
285
+ `Reached --max-iterations ${String(options.maxIterations)} before the coding-manager returned ${FINISH_MARK}.`,
286
+ );
287
+ }
288
+
289
+ async function writeText(filePath: string, content: string): Promise<void> {
290
+ await mkdir(path.dirname(filePath), { recursive: true });
291
+ await writeFile(filePath, `${content.trimEnd()}\n`, "utf8");
292
+ }
293
+
294
+ async function readGoal(goalPath: string): Promise<string> {
295
+ const goal = (await readFile(path.resolve(goalPath), "utf8")).trim();
296
+ if (goal === "") {
297
+ throw new Error(`Goal file must not be empty: ${goalPath}`);
298
+ }
299
+ return goal;
300
+ }
301
+
302
+ export const developingPipeline = definePipeline({
303
+ agentFactories,
304
+ parseArgs: parseDevelopingArgs,
305
+ run: developing,
306
+ });
@@ -0,0 +1,169 @@
1
+ import { type AgentFactoryMap, AgentTeam, type RecordCallback } from "coding-agent-forge";
2
+ import type { Agent } from "coding-agent-forge/agent";
3
+ import { parseArgs } from "node:util";
4
+ import { definePipeline, type ParsedPipelineArgs } from "../pipeline.js";
5
+ import {
6
+ agentFactories as developingAgentFactories,
7
+ TrajectoryOptimizerAgent,
8
+ type TrajectoryOptimizerVariables,
9
+ } from "./agents/index.js";
10
+ import {
11
+ developing,
12
+ type DevelopingAgentVariablesByName,
13
+ type DevelopingOptions,
14
+ } from "./pipeline.js";
15
+
16
+ export type DevelopingSkillAgentVariables = DevelopingAgentVariablesByName & {
17
+ "trajectory-optimizer": TrajectoryOptimizerVariables;
18
+ };
19
+
20
+ export type DevelopingSkillOptions = DevelopingOptions & {
21
+ metaskillPath: string;
22
+ };
23
+
24
+ const USAGE = [
25
+ "Usage: npm run developing-skill --",
26
+ "--config <path>",
27
+ "--target-path <folder>",
28
+ "--achive-dir <folder>",
29
+ "--artifact-path <folder>",
30
+ "--coding-style-skill-path <path>",
31
+ "--metaskill-path <path>",
32
+ "--paper-blueprint-path <path>",
33
+ "--experiment-plan-path <path>",
34
+ "--coding-plan-path <path>",
35
+ "--goal-path <path>",
36
+ "[--max-iterations <positive-integer>]",
37
+ "[--max-revision-iterations <positive-integer>]",
38
+ ].join(" ");
39
+
40
+ export function parseDevelopingSkillArgs(
41
+ args: readonly string[],
42
+ ): ParsedPipelineArgs<DevelopingSkillOptions> {
43
+ const {
44
+ values: {
45
+ config,
46
+ "target-path": targetPath,
47
+ "achive-dir": achiveDir,
48
+ "artifact-path": artifactPath,
49
+ "coding-style-skill-path": codingStyleSkillPath,
50
+ "metaskill-path": metaskillPath,
51
+ "paper-blueprint-path": paperBlueprintPath,
52
+ "experiment-plan-path": experimentPlanPath,
53
+ "coding-plan-path": codingPlanPath,
54
+ "goal-path": goalPath,
55
+ "max-iterations": maxIterations,
56
+ "max-revision-iterations": maxRevisionIterations,
57
+ },
58
+ } = parseArgs({
59
+ args: [...args],
60
+ options: {
61
+ config: { type: "string", multiple: true },
62
+ "target-path": { type: "string" },
63
+ "achive-dir": { type: "string" },
64
+ "artifact-path": { type: "string" },
65
+ "coding-style-skill-path": { type: "string" },
66
+ "metaskill-path": { type: "string" },
67
+ "paper-blueprint-path": { type: "string" },
68
+ "experiment-plan-path": { type: "string" },
69
+ "coding-plan-path": { type: "string" },
70
+ "goal-path": { type: "string" },
71
+ "max-iterations": { type: "string" },
72
+ "max-revision-iterations": { type: "string" },
73
+ },
74
+ });
75
+
76
+ if (
77
+ config === undefined ||
78
+ targetPath === undefined ||
79
+ achiveDir === undefined ||
80
+ artifactPath === undefined ||
81
+ codingStyleSkillPath === undefined ||
82
+ metaskillPath === undefined ||
83
+ paperBlueprintPath === undefined ||
84
+ experimentPlanPath === undefined ||
85
+ codingPlanPath === undefined ||
86
+ goalPath === undefined
87
+ ) {
88
+ throw new Error(USAGE);
89
+ }
90
+
91
+ return {
92
+ configPaths: config,
93
+ runningOptions: {
94
+ targetPath,
95
+ achiveDir,
96
+ artifactPath,
97
+ codingStyleSkillPath,
98
+ metaskillPath,
99
+ paperBlueprintPath,
100
+ experimentPlanPath,
101
+ codingPlanPath,
102
+ goalPath,
103
+ maxIterations: Number(maxIterations ?? 10),
104
+ maxRevisionIterations: Number(maxRevisionIterations ?? 3),
105
+ },
106
+ };
107
+ }
108
+
109
+ export async function developingSkill(
110
+ team: AgentTeam<DevelopingSkillAgentVariables>,
111
+ options: DevelopingSkillOptions,
112
+ ): Promise<void> {
113
+ const logRecord: RecordCallback = (thread, record) => {
114
+ console.log(thread.recordToPrettyString(record));
115
+ };
116
+ let trajectoryOptimizer: Agent<TrajectoryOptimizerVariables> | undefined;
117
+
118
+ await developing(team, {
119
+ ...options,
120
+ hooks: {
121
+ beforeRevisionLoop: async (agentVariables, currentTask) => {
122
+ trajectoryOptimizer = await team.createAgent("trajectory-optimizer");
123
+ const repositoryScan = (
124
+ await trajectoryOptimizer.runStreamed(
125
+ {
126
+ ...agentVariables,
127
+ phase: "scan",
128
+ currentTask,
129
+ },
130
+ logRecord,
131
+ )
132
+ ).trim();
133
+ console.log(`\n# Skill trajectory repository scan\n${repositoryScan}\n`);
134
+ },
135
+ afterTodoUpdate: async (agentVariables, currentTask, revisionReport, todoUpdateReport) => {
136
+ if (trajectoryOptimizer === undefined) {
137
+ throw new Error("Trajectory optimizer must scan the repository before optimizing.");
138
+ }
139
+
140
+ const optimizerReport = (
141
+ await trajectoryOptimizer.runStreamed(
142
+ {
143
+ ...agentVariables,
144
+ phase: "optimize",
145
+ currentTask,
146
+ revisionReport,
147
+ todoUpdateReport,
148
+ metaskillPath: options.metaskillPath,
149
+ },
150
+ logRecord,
151
+ )
152
+ ).trim();
153
+
154
+ console.log(`\n# Skill trajectory optimizer report\n${optimizerReport}\n`);
155
+ },
156
+ },
157
+ });
158
+ }
159
+
160
+ export const developingSkillAgentFactories: AgentFactoryMap = {
161
+ ...developingAgentFactories,
162
+ "trajectory-optimizer": (thread, constants) => new TrajectoryOptimizerAgent(thread, constants),
163
+ };
164
+
165
+ export const developingSkillPipeline = definePipeline({
166
+ agentFactories: developingSkillAgentFactories,
167
+ parseArgs: parseDevelopingSkillArgs,
168
+ run: developingSkill,
169
+ });