@autobe/agent 0.4.0 → 0.4.2

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 (35) hide show
  1. package/lib/analyze/AnalyzeAgent.d.ts +2 -2
  2. package/lib/analyze/AnalyzeAgent.js +75 -40
  3. package/lib/analyze/AnalyzeAgent.js.map +1 -1
  4. package/lib/analyze/AutoBeAnalyzeAgent.d.ts +24 -0
  5. package/lib/analyze/AutoBeAnalyzeAgent.js +972 -0
  6. package/lib/analyze/AutoBeAnalyzeAgent.js.map +1 -0
  7. package/lib/analyze/AutoBeAnalyzeFileSystem.d.ts +65 -0
  8. package/lib/analyze/{Planning.js → AutoBeAnalyzeFileSystem.js} +4 -4
  9. package/lib/analyze/AutoBeAnalyzeFileSystem.js.map +1 -0
  10. package/lib/analyze/AutoBeAnalyzeReviewer.d.ts +15 -0
  11. package/lib/analyze/AutoBeAnalyzeReviewer.js +42 -0
  12. package/lib/analyze/AutoBeAnalyzeReviewer.js.map +1 -0
  13. package/lib/constants/AutoBeSystemPromptConstant.d.ts +3 -2
  14. package/lib/constants/AutoBeSystemPromptConstant.js.map +1 -1
  15. package/lib/index.mjs +572 -113
  16. package/lib/index.mjs.map +1 -1
  17. package/lib/orchestrate/orchestrateAnalyze.js +512 -16
  18. package/lib/orchestrate/orchestrateAnalyze.js.map +1 -1
  19. package/lib/orchestrate/prisma/orchestratePrisma.js +1 -1
  20. package/lib/orchestrate/prisma/orchestratePrisma.js.map +1 -1
  21. package/package.json +4 -4
  22. package/src/analyze/AnalyzeAgent.ts +24 -19
  23. package/src/analyze/AutoBeAnalyzeAgent.ts +217 -0
  24. package/src/analyze/AutoBeAnalyzeFileSystem.ts +81 -0
  25. package/src/analyze/AutoBeAnalyzeReviewer.ts +60 -0
  26. package/src/constants/AutoBeSystemPromptConstant.ts +3 -2
  27. package/src/orchestrate/orchestrateAnalyze.ts +178 -17
  28. package/src/orchestrate/prisma/orchestratePrisma.ts +1 -1
  29. package/lib/analyze/CreateReviewerAgent.d.ts +0 -16
  30. package/lib/analyze/CreateReviewerAgent.js +0 -98
  31. package/lib/analyze/CreateReviewerAgent.js.map +0 -1
  32. package/lib/analyze/Planning.d.ts +0 -67
  33. package/lib/analyze/Planning.js.map +0 -1
  34. package/src/analyze/CreateReviewerAgent.ts +0 -126
  35. package/src/analyze/Planning.ts +0 -77
package/lib/index.mjs CHANGED
@@ -162,7 +162,7 @@ const getMissed = document => {
162
162
 
163
163
  function createApplication$6(props) {
164
164
  assertSchemaModel(props.model);
165
- const application = collection$8[props.model];
165
+ const application = collection$9[props.model];
166
166
  return {
167
167
  protocol: "class",
168
168
  name: "interface",
@@ -175,7 +175,7 @@ function createApplication$6(props) {
175
175
  };
176
176
  }
177
177
 
178
- const claude$8 = {
178
+ const claude$9 = {
179
179
  model: "claude",
180
180
  options: {
181
181
  reference: true,
@@ -281,7 +281,7 @@ const claude$8 = {
281
281
  } ]
282
282
  };
283
283
 
284
- const collection$8 = {
284
+ const collection$9 = {
285
285
  chatgpt: {
286
286
  model: "chatgpt",
287
287
  options: {
@@ -388,10 +388,10 @@ const collection$8 = {
388
388
  })()
389
389
  } ]
390
390
  },
391
- claude: claude$8,
392
- llama: claude$8,
393
- deepseek: claude$8,
394
- 3.1: claude$8,
391
+ claude: claude$9,
392
+ llama: claude$9,
393
+ deepseek: claude$9,
394
+ 3.1: claude$9,
395
395
  "3.0": {
396
396
  model: "3.0",
397
397
  options: {
@@ -609,7 +609,7 @@ async function process$2(ctx, operations, oldbie, remained) {
609
609
 
610
610
  function createApplication$5(props) {
611
611
  assertSchemaModel(props.model);
612
- const application = collection$7[props.model];
612
+ const application = collection$8[props.model];
613
613
  return {
614
614
  protocol: "class",
615
615
  name: "interface",
@@ -622,7 +622,7 @@ function createApplication$5(props) {
622
622
  };
623
623
  }
624
624
 
625
- const claude$7 = {
625
+ const claude$8 = {
626
626
  model: "claude",
627
627
  options: {
628
628
  reference: true,
@@ -754,7 +754,7 @@ const claude$7 = {
754
754
  } ]
755
755
  };
756
756
 
757
- const collection$7 = {
757
+ const collection$8 = {
758
758
  chatgpt: {
759
759
  model: "chatgpt",
760
760
  options: {
@@ -888,10 +888,10 @@ const collection$7 = {
888
888
  })()
889
889
  } ]
890
890
  },
891
- claude: claude$7,
892
- llama: claude$7,
893
- deepseek: claude$7,
894
- 3.1: claude$7,
891
+ claude: claude$8,
892
+ llama: claude$8,
893
+ deepseek: claude$8,
894
+ 3.1: claude$8,
895
895
  "3.0": {
896
896
  model: "3.0",
897
897
  options: {
@@ -1081,7 +1081,7 @@ async function orchestrateInterfaceEndpoints(ctx, content = "Make API endpoints
1081
1081
 
1082
1082
  function createApplication$4(props) {
1083
1083
  assertSchemaModel(props.model);
1084
- const application = collection$6[props.model];
1084
+ const application = collection$7[props.model];
1085
1085
  return {
1086
1086
  protocol: "class",
1087
1087
  name: "interface",
@@ -1094,7 +1094,7 @@ function createApplication$4(props) {
1094
1094
  };
1095
1095
  }
1096
1096
 
1097
- const claude$6 = {
1097
+ const claude$7 = {
1098
1098
  model: "claude",
1099
1099
  options: {
1100
1100
  reference: true,
@@ -1208,7 +1208,7 @@ const claude$6 = {
1208
1208
  } ]
1209
1209
  };
1210
1210
 
1211
- const collection$6 = {
1211
+ const collection$7 = {
1212
1212
  chatgpt: {
1213
1213
  model: "chatgpt",
1214
1214
  options: {
@@ -1314,10 +1314,10 @@ const collection$6 = {
1314
1314
  })()
1315
1315
  } ]
1316
1316
  },
1317
- claude: claude$6,
1318
- llama: claude$6,
1319
- deepseek: claude$6,
1320
- 3.1: claude$6,
1317
+ claude: claude$7,
1318
+ llama: claude$7,
1319
+ deepseek: claude$7,
1320
+ 3.1: claude$7,
1321
1321
  "3.0": {
1322
1322
  model: "3.0",
1323
1323
  options: {
@@ -1497,7 +1497,7 @@ async function process$1(ctx, endpoints) {
1497
1497
 
1498
1498
  function createApplication$3(props) {
1499
1499
  assertSchemaModel(props.model);
1500
- const application = collection$5[props.model];
1500
+ const application = collection$6[props.model];
1501
1501
  application.functions[0].validate = next => {
1502
1502
  const result = (() => {
1503
1503
  const _io0 = input => Array.isArray(input.operations) && input.operations.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
@@ -1787,7 +1787,7 @@ function createApplication$3(props) {
1787
1787
  };
1788
1788
  }
1789
1789
 
1790
- const claude$5 = {
1790
+ const claude$6 = {
1791
1791
  model: "claude",
1792
1792
  options: {
1793
1793
  reference: true,
@@ -2299,7 +2299,7 @@ const claude$5 = {
2299
2299
  } ]
2300
2300
  };
2301
2301
 
2302
- const collection$5 = {
2302
+ const collection$6 = {
2303
2303
  chatgpt: {
2304
2304
  model: "chatgpt",
2305
2305
  options: {
@@ -2802,10 +2802,10 @@ const collection$5 = {
2802
2802
  })()
2803
2803
  } ]
2804
2804
  },
2805
- claude: claude$5,
2806
- llama: claude$5,
2807
- deepseek: claude$5,
2808
- 3.1: claude$5,
2805
+ claude: claude$6,
2806
+ llama: claude$6,
2807
+ deepseek: claude$6,
2808
+ 3.1: claude$6,
2809
2809
  "3.0": {
2810
2810
  model: "3.0",
2811
2811
  options: {
@@ -3349,7 +3349,7 @@ const orchestrateInterface = ctx => async props => {
3349
3349
  return result;
3350
3350
  };
3351
3351
 
3352
- class Planning {
3352
+ class AutoBeAnalyzeFileSystem {
3353
3353
  constructor(fileMap = {}) {
3354
3354
  this.fileMap = fileMap;
3355
3355
  }
@@ -3369,41 +3369,58 @@ class Planning {
3369
3369
  }
3370
3370
  }
3371
3371
 
3372
- class AnalyzeAgent {
3373
- constructor(createReviewerAgentFn, ctx, pointer) {
3372
+ class AutoBeAnalyzeAgent {
3373
+ constructor(createReviewerAgentFn, ctx, pointer, filenames) {
3374
3374
  this.createReviewerAgentFn = createReviewerAgentFn;
3375
3375
  this.ctx = ctx;
3376
3376
  this.pointer = pointer;
3377
3377
  this.fileMap = {};
3378
3378
  assertSchemaModel(ctx.model);
3379
- const controller = createController({
3379
+ const controller = createController$1({
3380
3380
  model: ctx.model,
3381
- execute: new Planning(this.fileMap),
3381
+ execute: new AutoBeAnalyzeFileSystem(this.fileMap),
3382
3382
  build: async files => {
3383
3383
  this.pointer.value = {
3384
3384
  files
3385
3385
  };
3386
3386
  }
3387
3387
  });
3388
- this.createInnerAgent = () => {
3388
+ this.createAnalyzeAgent = () => {
3389
3389
  const agent = new MicroAgentica({
3390
3390
  controllers: [ controller ],
3391
3391
  model: ctx.model,
3392
3392
  vendor: ctx.vendor,
3393
3393
  config: {
3394
+ locale: ctx.config?.locale,
3394
3395
  systemPrompt: {
3395
- common: () => "You are the best planner.\nYou will write documents and hand it over to the developer.\nIt is advantageous to make several documents at once.\n\nThese are all the links that are currently referenced in the markdown. Please make sure to refer to them and don't forget to create the corresponding files.\nLike revision_history.md, you should not write fakes for content that does not exist yet. If written, it is only allowed if there is a user's request directly.\n\nPlease converse with the user based on the following guidelines and example templates.\nYou have to make a plan for the success of the user, and it has to be written in great detail to make the business successful.\nYour performance is measured by your customer's success.\nYou should listen to the reviewer and not make any requests to the reviewer.\nIf the reviewer asks for changes, revise the entire document from top to bottom,\nincorporating both the existing content and the requested changes. Do not add only the new parts—integrate them into a full rewrite of the document.\nFor example, if you are asked to modify or expand 'internal_bulletin_board_service_plan.md',\ndo not create a document such as 'internal_bulletin_board_service_plan_expanded.md'.\nonly update 'internal_bulletin_board_service_plan.md' file.\n\n# user information\n- user locale: {% User Locale %}\n\n\n# Guidelines\nIf the user specifies the exact number of pages, please follow it precisely.\n\n{% Guidelines %}\n\n\n# Docuemtation Style\nAs with example documents, it is better to divide the documents into several pieces.\nIf the amount user want is 30,000 characters, you'll have to write 10 tables of contents, and 3,000 characters per page.\nFor readability, even if the user requests it, a file should not exceed 3,000 characters. (The amount of text is measured in String(content).length)\n\nThe first page must be the page that made up the table of contents, and you may need to modify the table of contents at the request of the reviewer.\nTake advantage of the markdown link functionality OR write step by step (use overwrite function).\nFor example, rather than writing a long markdown document, create a markdown document that makes up the table of contents.\nYou can also draw a gantt chart for the development period.\n\nAnd hang the link in the document in advance, and create other files that correspond to the link.\nEven if it's not the first page, divide the documents if it's readable to write them separately.\nHyperlink features allow you to create more colorful documents.\nAlso, please put numbers in the front of the document as much as possible so that the files can be arranged well.\nIt is recommended to write a longer document (more than 3,000 letters).\n\nPlease make the file appropriate for user's language.\nDocuments and descriptions should be tailored to the language of the user.\n\nPlease refer to the document below. The document below has a total of 1,500 characters and should be longer.\n\n# Example Documentation\n{% Example Documentation %}\n\n# Abort\nIf you don't have anything more to ask for, call the 'abort' function instead of answering. Never answer the text.\nSimilarly, if the reviewer says there is nothing more to modify and it is perfect, call the function 'abort'.\n'abort' is one of the tool lists that you have been given.\nIf the reviewer says the document is complete, but it appears they are referring to only one out of several documents, then it is not yet the right time to abort.\n\nWrite a long document, but keep your answer short.".replace("{% Guidelines %}", "You are the “Planning Expert (PlannerAgent)” system agent.\nYou take full responsibility for all planning activities—from product planning through requirements analysis, design, and documentation—and you have extensive experience drafting planning documents.\n\n────────────────────────────────────────────────\n1. Persona & Roles\n • **Planning Expert**: Establish business objectives, craft user scenarios, and develop a strategic roadmap \n • **Communication Specialist**: Use a friendly yet professional tone, actively engaging with stakeholders \n • **Documentation Specialist**: Follow a structured approach (Table of Contents → Detailed TOC → Final Document) and deliver outputs in Markdown\n\n2. Conversation-Driven Extraction Framework (WHY → WHAT → HOW)\n 1. **WHY (Reason for the Problem)**\n * “Why is this feature/project needed?” “What business or user problem does it solve?” \n * Ask questions to clearly gather background, KPIs, and success criteria \n 2. **WHAT (What to Solve)**\n * “What must be implemented?” “What are the key functional and non-functional requirements?” \n * Distinguish between functional vs. non-functional, organize business requirements and user scenarios \n 3. **HOW (How to Execute)**\n * “What flow and structure will the service follow?” “How should the data model and ERD be designed?”\n\n3. Scope & Constraints\n • Do **not** produce development-level documentation (backend, frontend, or infrastructure tech stacks). \n • API design, database structure, and architecture reviews should be suggested only at a high level from a planning perspective—avoid any detailed code or configuration references.\n\n4. Deliverable Structuring Guidelines\n 1. **Present the TOC First**\n * Propose only the top-level Table of Contents initially; generate detailed sub-headings after user approval \n * When sub-TOCs grow large, split them into separate Markdown files and interlink them \n 2. **Document Augmentation**\n * Each document may be continuously updated; you may pre-link to future documents as placeholders \n * Only use links to actual, existing document paths—external URLs that don’t exist are prohibited \n 3. **Document Components**\n * Include: Overview, Objectives, User Personas, User Journeys, Functional & Non-Functional Requirements, Acceptance Criteria, ERD \n * Use tables, lists, and diagrams (ASCII or Mermaid) wherever helpful\n\n5. Communication & Feedback\n • After each phase, summarize progress and ask for the user’s confirmation (e.g., “Shall we proceed with this TOC?”) \n • Upon completing a document: include a feedback prompt such as “Is there anything else to refine?”\n\n6. Final Deliverables\n • Provide everything in Markdown (`.md`) format \n • Include inter-document reference links \n • Do **not** finalize the “completed” version until the user has given explicit approval\n\n7. Review Loop\n • Use a while-loop process: after drafting any part, send it to the review agent and iterate until they grant approval. \n • Do not advance to the next section until the review agent confirms the current one meets quality standards.\n\n8. Approval & File Generation\n • Once the review agent approves the final draft, use the available tools to generate and export the document file. \n\n9. Iterative Writing Flow\n • Always start by proposing the top-level Table of Contents. \n • After TOC approval, draft the document one section (paragraph) at a time, submitting each for review before proceeding.").replace("{% Example Documentation %}", "```기획서\n# 아보카도 마켓 (Avocado Market)\n\n**서비스 상세 기획 보고서**\n\n---\n\n## 1. 서비스 개요\n\n**아보카도 마켓**은 지역 기반 중고 거래를 넘어, **친환경 가치와 커뮤니티 중심의 연결**을 지향하는 차세대 중고거래 플랫폼입니다.\n사용자는 누구나 쉽고 안전하게 중고 물품을 사고팔 수 있으며, 지역 이웃과의 교류를 통해 지속 가능한 생활을 실현할 수 있습니다.\n👉 [자세히 보기](01_overview.md)\n\n---\n\n## 2. 시장 조사 및 벤치마킹\n\n국내외 중고거래 플랫폼 시장 현황을 종합 분석하고, 주요 경쟁사의 서비스 전략과 차별 요소를 비교하였습니다. 또한, 향후 시장 성장 가능성과 트렌드도 함께 제시합니다.\n👉 [자세히 보기](02_market_analysis.md)\n\n---\n\n## 3. 주요 기능 및 상세 설명\n\n아보카도 마켓이 제공하는 핵심 기능들과 실제 사용 시나리오를 구체적으로 설명합니다. 각 기능의 목적, 사용자에게 제공되는 가치, 차별화된 기술 또는 UI 요소를 포함합니다.\n👉 [자세히 보기](03_features.md)\n\n---\n\n## 4. 수익 모델 및 성장 전략\n\n광고, 프리미엄 서비스, 제휴 기반 비즈니스 등 다양한 수익화 모델을 제시하며, 이를 기반으로 한 중장기 성장 전략을 포함합니다.\n👉 [자세히 보기](04_business_model.md)\n\n---\n\n## 5. UX/UI 설계 가이드\n\n사용자 친화적 인터페이스 설계 방안과 함께, 레퍼런스 사례 및 사용자 경험 향상을 위한 디자인 원칙을 제공합니다.\n👉 [자세히 보기](05_uxui_guidelines.md)\n\n---\n\n## 6. 개발 및 출시 전략\n\n서비스 개발부터 MVP 설계, 베타 테스트, 정식 출시까지의 전체 로드맵을 제시하며, 각 단계별 목표와 전략을 구체화합니다.\n👉 [자세히 보기](06_release_strategy.md)\n\n---\n\n## 7. 기술 아키텍처\n\n플랫폼의 전체 시스템 구조, 핵심 기술 스택, 외부 API 연동 방식, 인프라 구성 등을 포함한 기술적 설계 내용을 정리합니다.\n👉 [자세히 보기](07_architecture.md)\n\n---\n\n## 8. 포지셔닝 및 마케팅 전략\n\n타깃 사용자 정의, 브랜드 아이덴티티 수립, 홍보 전략, 지역 밀착형 커뮤니티 마케팅 등 실질적인 실행 전략을 제안합니다.\n👉 [자세히 보기](08_marketing.md)\n\n---\n\n## 9. 리스크 관리 방안\n\n서비스 운영 전반에서 발생할 수 있는 다양한 리스크를 식별하고, 이에 대한 사전 예방 및 사후 대응 방안을 체계적으로 정리하였습니다.\n👉 [자세히 보기](09_risk_management.md)\n\n---\n\n## 10. 서비스 확장 가능성\n\n중장기적으로 고려할 수 있는 신규 기능, 비즈니스 모델 확장, 글로벌 진출 등 아보카도 마켓의 미래 비전을 제시합니다.\n👉 [자세히 보기](10_expansion.md)\n\n```;").replace("{% User Locale %}", ctx.config?.locale ?? "en-US"),
3396
3396
  describe: () => "Answer only 'completion' or 'failure'."
3397
3397
  }
3398
3398
  },
3399
3399
  tokenUsage: ctx.usage(),
3400
- histories: []
3400
+ histories: [ {
3401
+ type: "systemMessage",
3402
+ text: "# Overview\nYou are the best planner.\nYou will write documents and hand it over to the developer.\nYou are only asked to fill out one document.\n\nLike revision_history.md, you should not write fakes for content that does not exist yet. If written, it is only allowed if there is a user's request directly.\n\nPlease converse with the user based on the following guidelines and example templates. \nYou have to make a plan for the success of the user, and it has to be written in great detail to make the business successful. \nYour performance is measured by your customer's success. \nYou should listen to the reviewer and not make any requests to the reviewer. \nIf the reviewer asks for changes, revise the entire document from top to bottom,\nincorporating both the existing content and the requested changes. Do not add only the new parts—integrate them into a full rewrite of the document. \nFor example, if you are asked to modify or expand 'internal_bulletin_board_service_plan.md',\ndo not create a document such as 'internal_bulletin_board_service_plan_expanded.md'. \nonly update 'internal_bulletin_board_service_plan.md' file. \n\nWrite a long document, but keep your answer short.\n\n# Number of documents that need to be created\nThe number of documents requested by the user, or the amount of documents sufficient for developers to develop\n\n# user information\n- user locale: {% User Locale %}\n\nCreate and review documents for your locale.\nIt must match the language of the user.\n\n# Documentation Style\nFor readability, even if the user requests it, a file should not exceed 3,000 characters. (The amount of text is measured in String(content).length)\nHyperlink features allow you to create more colorful documents.\n\nPlease make the file appropriate for user's language.\nDocuments and descriptions should be tailored to the language of the user.\n\nPlease refer to the document below. The document below has a total of 1,500 characters and should be longer.\nNever insert a question in the document.\n\n\n# abort\nIf you have no further requests or questions, immediately call the 'abort' function instead of replying with text. Never respond with additional text.\n\nWhen the reviewer determines the document is perfect and requires no more modifications, they must call the 'abort' function without hesitation.\n\n'abort' is a tool you must use to signal completion.\n\nDo not delay or avoid calling 'abort' once the document is complete.\n\nIf the reviewer says the document is complete but only one document out of multiple remains unfinished, do NOT call 'abort' yet.\n\nIf the reviewer requests creation or modification of any document other than the current assigned one, **ignore such requests** and continue focusing only on the current document. \nIn this case, the reviewer may call 'abort' to forcibly terminate the review.\n\nWrite a long document, but keep your answer short.".replace("{% User Locale %}", ctx.config?.locale ?? "en-US")
3403
+ }, {
3404
+ type: "systemMessage",
3405
+ text: [ "# Guidelines", "If the user specifies the exact number of pages, please follow it precisely.", "You are the “Planning Expert (PlannerAgent)” system agent.\nYou take full responsibility for all planning activities—from product planning through requirements analysis, design, and documentation—and you have extensive experience drafting planning documents.\n\n────────────────────────────────────────────────\n1. Persona & Roles\n • **Planning Expert**: Establish business objectives, craft user scenarios, and develop a strategic roadmap \n • **Communication Specialist**: Use a friendly yet professional tone, actively engaging with stakeholders \n • **Documentation Specialist**: Follow a structured approach (Table of Contents → Detailed TOC → Final Document) and deliver outputs in Markdown\n\n2. Conversation-Driven Extraction Framework (WHY → WHAT → HOW)\n 1. **WHY (Reason for the Problem)**\n * “Why is this feature/project needed?” “What business or user problem does it solve?” \n * Ask questions to clearly gather background, KPIs, and success criteria \n 2. **WHAT (What to Solve)**\n * “What must be implemented?” “What are the key functional and non-functional requirements?” \n * Distinguish between functional vs. non-functional, organize business requirements and user scenarios \n 3. **HOW (How to Execute)**\n * “What flow and structure will the service follow?” “How should the data model and ERD be designed?”\n\n3. Scope & Constraints\n • Do **not** produce development-level documentation (backend, frontend, or infrastructure tech stacks). \n • API design, database structure, and architecture reviews should be suggested only at a high level from a planning perspective—avoid any detailed code or configuration references.\n\n4. Deliverable Structuring Guidelines\n 1. **Present the TOC First**\n * Propose only the top-level Table of Contents initially; generate detailed sub-headings after user approval \n * When sub-TOCs grow large, split them into separate Markdown files and interlink them \n 2. **Document Augmentation**\n * Each document may be continuously updated; you may pre-link to future documents as placeholders \n * Only use links to actual, existing document paths—external URLs that don’t exist are prohibited \n 3. **Document Components**\n * Include: Overview, Objectives, User Personas, User Journeys, Functional & Non-Functional Requirements, Acceptance Criteria, ERD \n * Use tables, lists, and diagrams (ASCII or Mermaid) wherever helpful\n\n5. Communication & Feedback\n • After each phase, summarize progress and ask for the user’s confirmation (e.g., “Shall we proceed with this TOC?”) \n • Upon completing a document: include a feedback prompt such as “Is there anything else to refine?”\n\n6. Final Deliverables\n • Provide everything in Markdown (`.md`) format \n • Include inter-document reference links \n • Do **not** finalize the “completed” version until the user has given explicit approval\n\n7. Review Loop\n • Use a while-loop process: after drafting any part, send it to the review agent and iterate until they grant approval. \n • Do not advance to the next section until the review agent confirms the current one meets quality standards.\n\n8. Approval & File Generation\n • Once the review agent approves the final draft, use the available tools to generate and export the document file. \n\n9. Iterative Writing Flow\n • Always start by proposing the top-level Table of Contents. \n • After TOC approval, draft the document one section (paragraph) at a time, submitting each for review before proceeding." ].join("\n")
3406
+ }, {
3407
+ type: "systemMessage",
3408
+ text: [ "The following is the name of the entire file.", "Use it to build a table of contents.", filenames.map((filename => `- ${filename}`)), "", "However, do not touch other than the file you have to create." ].join("\n")
3409
+ } ]
3401
3410
  });
3411
+ agent.on("request", (event => {
3412
+ if (event.body.tools) {
3413
+ event.body.tool_choice = "required";
3414
+ }
3415
+ }));
3402
3416
  return agent;
3403
3417
  };
3404
3418
  }
3405
- async conversate(content) {
3406
- const response = await this.createInnerAgent().conversate(content);
3419
+ async conversate(content, retry = 3) {
3420
+ if (retry === 0) {
3421
+ return "Abort due to excess retry count";
3422
+ }
3423
+ const response = await this.createAnalyzeAgent().conversate(content);
3407
3424
  const lastMessage = response[response.length - 1];
3408
3425
  if ("text" in lastMessage) {
3409
3426
  this.ctx.dispatch({
@@ -3421,12 +3438,13 @@ class AnalyzeAgent {
3421
3438
  if (aborted === true) {
3422
3439
  return lastMessage.text;
3423
3440
  }
3424
- const currentFiles = this.fileMap;
3425
3441
  const reviewer = this.createReviewerAgentFn(this.ctx, {
3426
3442
  query: content,
3427
- currentFiles
3443
+ files: JSON.stringify(this.fileMap)
3428
3444
  });
3429
- const [review] = await reviewer.conversate(lastMessage.text);
3445
+ const filenames = Object.keys(this.fileMap).join(",");
3446
+ const command = `Request for review of these files.: ${filenames}`;
3447
+ const [review] = await reviewer.conversate(command);
3430
3448
  if (review) {
3431
3449
  if (review.type === "assistantMessage") {
3432
3450
  this.ctx.dispatch({
@@ -3439,18 +3457,18 @@ class AnalyzeAgent {
3439
3457
  user_query: content,
3440
3458
  message: `THIS IS ANSWER OF REVIEW AGENT. FOLLOW THIS INSTRUCTIONS. AND DON'T REQUEST ANYTHING.`,
3441
3459
  review: review.text
3442
- }));
3460
+ }), retry--);
3443
3461
  }
3444
3462
  }
3445
- return `If the document is not 1,000 characters, please fill it out in more abundance, and if it exceeds 1,000 characters, please fill out the next document. If you don't have the next document, you can exit now.`;
3463
+ return `COMPLETE WITHOUT REVIEW`;
3446
3464
  }
3447
3465
  return "COMPLETE";
3448
3466
  }
3449
3467
  }
3450
3468
 
3451
- function createController(props) {
3469
+ function createController$1(props) {
3452
3470
  assertSchemaModel(props.model);
3453
- const application = collection$4[props.model];
3471
+ const application = collection$5[props.model];
3454
3472
  return {
3455
3473
  protocol: "class",
3456
3474
  name: "Planning",
@@ -3475,7 +3493,7 @@ function createController(props) {
3475
3493
  };
3476
3494
  }
3477
3495
 
3478
- const claude$4 = {
3496
+ const claude$5 = {
3479
3497
  model: "claude",
3480
3498
  options: {
3481
3499
  reference: true,
@@ -3489,21 +3507,27 @@ const claude$4 = {
3489
3507
  files: {
3490
3508
  type: "array",
3491
3509
  items: {
3510
+ description: "Current Type: {@link IFile}",
3492
3511
  type: "object",
3493
3512
  properties: {
3494
3513
  reason: {
3514
+ description: "Describe briefly why you made this document, and if you have any plans for\nthe next one.",
3495
3515
  type: "string"
3496
3516
  },
3497
3517
  filename: {
3518
+ title: "Filename to generate or overwrite",
3519
+ description: "Filename to generate or overwrite.",
3498
3520
  type: "string",
3499
3521
  pattern: "((.*)\\.md)$"
3500
3522
  },
3501
3523
  markdown: {
3524
+ description: 'Markdown file content. Only write the content of the file. Do not include\nany questions. This should contain only the contents of the file. Do not\nwrite down any questions or appreciation. For example, remove a sentence\nsuch as "Is it okay if we proceed with the table of contents? Please let me\nknow if there is anything to add or exclude from the table of contents!"',
3502
3525
  type: "string"
3503
3526
  }
3504
3527
  },
3505
3528
  required: [ "reason", "filename", "markdown" ]
3506
- }
3529
+ },
3530
+ minItems: 1
3507
3531
  }
3508
3532
  },
3509
3533
  required: [ "files" ],
@@ -3511,23 +3535,27 @@ const claude$4 = {
3511
3535
  $defs: {}
3512
3536
  },
3513
3537
  validate: (() => {
3514
- const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
3538
+ const _io0 = input => Array.isArray(input.files) && (1 <= input.files.length && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem))));
3515
3539
  const _io1 = input => "string" === typeof input.reason && ("string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename)) && "string" === typeof input.markdown;
3516
3540
  const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
3517
3541
  path: _path + ".files",
3518
- expected: "Array<__type>",
3542
+ expected: "(Array<IFile> & MinItems<1>)",
3543
+ value: input.files
3544
+ })) && ((1 <= input.files.length || _report(_exceptionable, {
3545
+ path: _path + ".files",
3546
+ expected: "Array<> & MinItems<1>",
3519
3547
  value: input.files
3520
3548
  })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
3521
3549
  path: _path + ".files[" + _index2 + "]",
3522
- expected: "__type.o1",
3550
+ expected: "IFile",
3523
3551
  value: elem
3524
3552
  })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
3525
3553
  path: _path + ".files[" + _index2 + "]",
3526
- expected: "__type.o1",
3554
+ expected: "IFile",
3527
3555
  value: elem
3528
- }))).every((flag => flag)) || _report(_exceptionable, {
3556
+ }))).every((flag => flag))) || _report(_exceptionable, {
3529
3557
  path: _path + ".files",
3530
- expected: "Array<__type>",
3558
+ expected: "(Array<IFile> & MinItems<1>)",
3531
3559
  value: input.files
3532
3560
  }) ].every((flag => flag));
3533
3561
  const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.reason || _report(_exceptionable, {
@@ -3578,9 +3606,12 @@ const claude$4 = {
3578
3606
  }, {
3579
3607
  name: "removeFile",
3580
3608
  parameters: {
3609
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
3581
3610
  type: "object",
3582
3611
  properties: {
3583
3612
  filename: {
3613
+ title: "Filename to generate or overwrite",
3614
+ description: "Filename to generate or overwrite.",
3584
3615
  type: "string",
3585
3616
  pattern: "((.*)\\.md)$"
3586
3617
  }
@@ -3605,11 +3636,11 @@ const claude$4 = {
3605
3636
  _report = __typia_transform__validateReport._validateReport(errors);
3606
3637
  ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
3607
3638
  path: _path + "",
3608
- expected: "__type",
3639
+ expected: 'Pick<IFile, "filename">',
3609
3640
  value: input
3610
3641
  })) && _vo0(input, _path + "", true) || _report(true, {
3611
3642
  path: _path + "",
3612
- expected: "__type",
3643
+ expected: 'Pick<IFile, "filename">',
3613
3644
  value: input
3614
3645
  }))(input, "$input", true);
3615
3646
  const success = 0 === errors.length;
@@ -3708,7 +3739,7 @@ const claude$4 = {
3708
3739
  } ]
3709
3740
  };
3710
3741
 
3711
- const collection$4 = {
3742
+ const collection$5 = {
3712
3743
  chatgpt: {
3713
3744
  model: "chatgpt",
3714
3745
  options: {
@@ -3722,18 +3753,23 @@ const collection$4 = {
3722
3753
  type: "object",
3723
3754
  properties: {
3724
3755
  files: {
3756
+ description: "@minItems 1",
3725
3757
  type: "array",
3726
3758
  items: {
3759
+ description: "Current Type: {@link IFile}",
3727
3760
  type: "object",
3728
3761
  properties: {
3729
3762
  reason: {
3763
+ description: "Describe briefly why you made this document, and if you have any plans for\nthe next one.",
3730
3764
  type: "string"
3731
3765
  },
3732
3766
  filename: {
3733
- description: "@pattern ((.*)\\.md)$",
3767
+ title: "Filename to generate or overwrite",
3768
+ description: "Filename to generate or overwrite.\n\n\n@pattern ((.*)\\.md)$",
3734
3769
  type: "string"
3735
3770
  },
3736
3771
  markdown: {
3772
+ description: 'Markdown file content. Only write the content of the file. Do not include\nany questions. This should contain only the contents of the file. Do not\nwrite down any questions or appreciation. For example, remove a sentence\nsuch as "Is it okay if we proceed with the table of contents? Please let me\nknow if there is anything to add or exclude from the table of contents!"',
3737
3773
  type: "string"
3738
3774
  }
3739
3775
  },
@@ -3746,23 +3782,27 @@ const collection$4 = {
3746
3782
  $defs: {}
3747
3783
  },
3748
3784
  validate: (() => {
3749
- const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
3785
+ const _io0 = input => Array.isArray(input.files) && (1 <= input.files.length && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem))));
3750
3786
  const _io1 = input => "string" === typeof input.reason && ("string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename)) && "string" === typeof input.markdown;
3751
3787
  const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
3752
3788
  path: _path + ".files",
3753
- expected: "Array<__type>",
3789
+ expected: "(Array<IFile> & MinItems<1>)",
3790
+ value: input.files
3791
+ })) && ((1 <= input.files.length || _report(_exceptionable, {
3792
+ path: _path + ".files",
3793
+ expected: "Array<> & MinItems<1>",
3754
3794
  value: input.files
3755
3795
  })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
3756
3796
  path: _path + ".files[" + _index2 + "]",
3757
- expected: "__type.o1",
3797
+ expected: "IFile",
3758
3798
  value: elem
3759
3799
  })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
3760
3800
  path: _path + ".files[" + _index2 + "]",
3761
- expected: "__type.o1",
3801
+ expected: "IFile",
3762
3802
  value: elem
3763
- }))).every((flag => flag)) || _report(_exceptionable, {
3803
+ }))).every((flag => flag))) || _report(_exceptionable, {
3764
3804
  path: _path + ".files",
3765
- expected: "Array<__type>",
3805
+ expected: "(Array<IFile> & MinItems<1>)",
3766
3806
  value: input.files
3767
3807
  }) ].every((flag => flag));
3768
3808
  const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.reason || _report(_exceptionable, {
@@ -3813,10 +3853,12 @@ const collection$4 = {
3813
3853
  }, {
3814
3854
  name: "removeFile",
3815
3855
  parameters: {
3856
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
3816
3857
  type: "object",
3817
3858
  properties: {
3818
3859
  filename: {
3819
- description: "@pattern ((.*)\\.md)$",
3860
+ title: "Filename to generate or overwrite",
3861
+ description: "Filename to generate or overwrite.\n\n\n@pattern ((.*)\\.md)$",
3820
3862
  type: "string"
3821
3863
  }
3822
3864
  },
@@ -3840,11 +3882,11 @@ const collection$4 = {
3840
3882
  _report = __typia_transform__validateReport._validateReport(errors);
3841
3883
  ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
3842
3884
  path: _path + "",
3843
- expected: "__type",
3885
+ expected: 'Pick<IFile, "filename">',
3844
3886
  value: input
3845
3887
  })) && _vo0(input, _path + "", true) || _report(true, {
3846
3888
  path: _path + "",
3847
- expected: "__type",
3889
+ expected: 'Pick<IFile, "filename">',
3848
3890
  value: input
3849
3891
  }))(input, "$input", true);
3850
3892
  const success = 0 === errors.length;
@@ -3943,10 +3985,10 @@ const collection$4 = {
3943
3985
  }))()
3944
3986
  } ]
3945
3987
  },
3946
- claude: claude$4,
3947
- llama: claude$4,
3948
- deepseek: claude$4,
3949
- 3.1: claude$4,
3988
+ claude: claude$5,
3989
+ llama: claude$5,
3990
+ deepseek: claude$5,
3991
+ 3.1: claude$5,
3950
3992
  "3.0": {
3951
3993
  model: "3.0",
3952
3994
  options: {
@@ -3965,42 +4007,52 @@ const collection$4 = {
3965
4007
  type: "object",
3966
4008
  properties: {
3967
4009
  reason: {
3968
- type: "string"
4010
+ type: "string",
4011
+ description: "Describe briefly why you made this document, and if you have any plans for\nthe next one."
3969
4012
  },
3970
4013
  filename: {
3971
4014
  type: "string",
3972
- pattern: "((.*)\\.md)$"
4015
+ pattern: "((.*)\\.md)$",
4016
+ title: "Filename to generate or overwrite",
4017
+ description: "Filename to generate or overwrite."
3973
4018
  },
3974
4019
  markdown: {
3975
- type: "string"
4020
+ type: "string",
4021
+ description: 'Markdown file content. Only write the content of the file. Do not include\nany questions. This should contain only the contents of the file. Do not\nwrite down any questions or appreciation. For example, remove a sentence\nsuch as "Is it okay if we proceed with the table of contents? Please let me\nknow if there is anything to add or exclude from the table of contents!"'
3976
4022
  }
3977
4023
  },
3978
4024
  required: [ "reason", "filename", "markdown" ],
4025
+ description: "Current Type: {@link IFile}",
3979
4026
  additionalProperties: false
3980
- }
4027
+ },
4028
+ minItems: 1
3981
4029
  }
3982
4030
  },
3983
4031
  required: [ "files" ],
3984
4032
  additionalProperties: false
3985
4033
  },
3986
4034
  validate: (() => {
3987
- const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
4035
+ const _io0 = input => Array.isArray(input.files) && (1 <= input.files.length && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem))));
3988
4036
  const _io1 = input => "string" === typeof input.reason && ("string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename)) && "string" === typeof input.markdown;
3989
4037
  const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
3990
4038
  path: _path + ".files",
3991
- expected: "Array<__type>",
4039
+ expected: "(Array<IFile> & MinItems<1>)",
4040
+ value: input.files
4041
+ })) && ((1 <= input.files.length || _report(_exceptionable, {
4042
+ path: _path + ".files",
4043
+ expected: "Array<> & MinItems<1>",
3992
4044
  value: input.files
3993
4045
  })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
3994
4046
  path: _path + ".files[" + _index2 + "]",
3995
- expected: "__type.o1",
4047
+ expected: "IFile",
3996
4048
  value: elem
3997
4049
  })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
3998
4050
  path: _path + ".files[" + _index2 + "]",
3999
- expected: "__type.o1",
4051
+ expected: "IFile",
4000
4052
  value: elem
4001
- }))).every((flag => flag)) || _report(_exceptionable, {
4053
+ }))).every((flag => flag))) || _report(_exceptionable, {
4002
4054
  path: _path + ".files",
4003
- expected: "Array<__type>",
4055
+ expected: "(Array<IFile> & MinItems<1>)",
4004
4056
  value: input.files
4005
4057
  }) ].every((flag => flag));
4006
4058
  const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.reason || _report(_exceptionable, {
@@ -4055,10 +4107,13 @@ const collection$4 = {
4055
4107
  properties: {
4056
4108
  filename: {
4057
4109
  type: "string",
4058
- pattern: "((.*)\\.md)$"
4110
+ pattern: "((.*)\\.md)$",
4111
+ title: "Filename to generate or overwrite",
4112
+ description: "Filename to generate or overwrite."
4059
4113
  }
4060
4114
  },
4061
4115
  required: [ "filename" ],
4116
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4062
4117
  additionalProperties: false
4063
4118
  },
4064
4119
  validate: (() => {
@@ -4077,11 +4132,11 @@ const collection$4 = {
4077
4132
  _report = __typia_transform__validateReport._validateReport(errors);
4078
4133
  ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
4079
4134
  path: _path + "",
4080
- expected: "__type",
4135
+ expected: 'Pick<IFile, "filename">',
4081
4136
  value: input
4082
4137
  })) && _vo0(input, _path + "", true) || _report(true, {
4083
4138
  path: _path + "",
4084
- expected: "__type",
4139
+ expected: 'Pick<IFile, "filename">',
4085
4140
  value: input
4086
4141
  }))(input, "$input", true);
4087
4142
  const success = 0 === errors.length;
@@ -4180,42 +4235,30 @@ const collection$4 = {
4180
4235
  }
4181
4236
  };
4182
4237
 
4183
- const createReviewerAgent = (ctx, input) => {
4184
- const markdownFiles = Array.from(new Set(Object.values(input.currentFiles).flatMap((content => {
4185
- const fileExtensions = [ "md" ];
4186
- const regex = /\[[^\]]*\]\(([^)]+)\)/g;
4187
- const fileLinks = [ ...content.matchAll(regex) ].map((match => match[1])).filter((link => {
4188
- const ext = link.split(".").pop()?.toLowerCase();
4189
- return ext && fileExtensions.includes(ext);
4190
- }));
4191
- return fileLinks;
4192
- }))));
4238
+ const AutoBeAnalyzeReviewer = (ctx, input) => {
4193
4239
  const agent = new MicroAgentica({
4194
4240
  model: ctx.model,
4195
4241
  vendor: ctx.vendor,
4196
4242
  controllers: [],
4197
4243
  config: {
4198
4244
  systemPrompt: {
4199
- common: () => [ "You are an excellent requirements analyst & reviewer agent.", "", `The reviewer's role is to ensure that this document contains sufficient information before it is delivered to developers`, `These are all the links that are currently referenced in the markdown. Please make sure to refer to them and don't forget to create the corresponding files.`, "Also, you should not create files that are not specified in the table of contents.", "If you request the creation of a file that is not specified in the table of contents, instruct them to modify the table of contents first.", "If the user specifies the exact number of pages, please follow it precisely.", "", "You should not write your own writing in any case, but only direct the modifications.", "Also, reviewers are independent beings, and should never be instructed.", "Your words should be instructions that must be followed, not recommendations.", "", `user said, "${input.query}"`, "user requests will take precedence over the other system prompts below unless they are a security concern.", "", "If there are any changes that need to be made, please provide detailed instructions.", "Just give clear and concise instructions, but don't say anything unnecessary.", "", "If you feel that the current level of analysis is sufficient, please do not make any further requests and notify us that it is complete.", "", "It is recommended to ask the planner to write a longer document (more than 1,000 letters) until it gives sufficient utility value.", "However, even if the length of the document is less than 1,000 letters, pass it if the quality is compliant.", "When increasing the volume of a document, explain to the planner how many letters the document currently has and how many more should be increased.", "Rather than simply telling them to increase the text, it is better to count the number of tables of contents compared to the existing text and instruct them to double the amount if they want to double the amount.", "When you add something about the table of contents, please clearly state the name of the table of contents.", "", "If the planner agent asks a question, the reviewer should answer on behalf of the user.", "Please do not ask any questions.", "Just give orders.", "", "If you have a hyperlink that is not yet complete, even if the document is of good quality, the document is considered incomplete.", "You should also ask for the rest of the document to be created.", "At this time, the document should be newly created with the name attached to the link, not modified.", "<CurrentFiles>", JSON.stringify(Object.entries(input.currentFiles).map((([filename, content]) => ({
4200
- filename,
4201
- content,
4202
- content_length: content.length
4203
- })))), "</CurrentFiles>", "", `These are all the links that are currently referenced in the markdown. Please make sure to refer to them and don't forget to create the corresponding files.`, `<Linked Files>`, markdownFiles.map((filename => {
4204
- const isChecked = Object.keys(input.currentFiles).includes(filename);
4205
- return `- [${isChecked}] ${filename}`;
4206
- })), `</Linked Files>`, "", "Write a long document, but keep your answer short.", "If you say the document is complete, the planner will finish writing the document.", "If only one document has been written out of several that need to be completed, do not simply state that it is complete—also provide instructions for what should be done next.", "For example, if you say, “The document internal_bulletin_board_service_plan.md has already been written with over 1,000 characters. Its quality is sufficient, so mark it as complete without any further requests,” then the planner will respond with “Got it!” and stop writing—even if there are still remaining documents.", "Be cautious: the planner will try to avoid work by interpreting your words in a way that lets them do less.", "The correct response from you should be:", "“The document's quality is sufficient, so mark it as complete without any further requests. Now, proceed to write the next documents immediately.”", "When requesting the next document to be written, you must include both the document title and a brief description of its content." ].join("\n"),
4207
4245
  describe: () => "Answer only 'completion' or 'failure'."
4208
- }
4246
+ },
4247
+ locale: ctx.config?.locale
4209
4248
  },
4249
+ histories: [ ...ctx.histories().filter((el => el.type === "assistantMessage" || el.type === "userMessage")), {
4250
+ type: "systemMessage",
4251
+ text: "# Reviewer Agent Operating Guidelines\n\n## Core Principles\n\n* **Only review the document currently being viewed.**\n* Even if there is a section that implies another document, **ignore it.**\n* Even if the current page is a table of contents, **do not request the creation of any other pages.**\n* If a new document is referenced even though the current document is not a table of contents page that begins with `00`,\n **instruct the planner to clear all content and rewrite the document.**\n* Other documents will be brought in by other agents, so do **not** request the creation of any files other than the current one.\n* **Each agent must write only the single page assigned to them.** \n Requests or attempts to write other pages or documents are strictly prohibited.\n* When references to other documents appear in the current page, do not request creation of those documents. Instead, \n **instruct the planner to clear all contents and rewrite the current document.**\n\n## Role of the Reviewer\n\n* The reviewer's role is to **ensure the document contains sufficient information before it is delivered to developers.**\n* Below are all the **links currently referenced in the markdown**. Be sure to refer to them and **ensure the corresponding files are created.**\n* **Do not create files that are not specified in the table of contents.**\n* If the user specifies the **exact number of pages**, that number **must be followed exactly.**\n* Reviewers are limited to reviewing **only their assigned single page** and must not engage with other pages or documents.\n* If an agent requests creation of other pages or documents, \n the reviewer must issue a command to **stop such requests and enforce focus on the current page only.**\n\n## Prohibited Actions\n\n* The reviewer must **never write their own content under any circumstances.**\n* Reviewers are **independent beings and must never be instructed.**\n* The reviewer's words must be **commands that must be followed, not recommendations.**\n\n## Instructions for Revisions\n\n* If changes are necessary, **provide detailed instructions.**\n* Give **clear and concise instructions**, and **avoid unnecessary remarks.**\n* If the document is too short or insufficient, compare the number of headings to the text length and \n **instruct the analyze agent to expand the content within the current page accordingly.**\n* If hyperlinks point to content not included in the current page, \n **instruct the analyze agent to add a new section with the hyperlink’s title under the appropriate heading within the same page.**\n\n## If the Document is Sufficient\n\n* If the current level of analysis is deemed sufficient, **make no further requests.**\n* **Notify that the document is complete.**\n\n---\n\n# Guidelines for Document Volume\n\n* It is recommended to instruct the analyze agent to **write a document longer than 2,000 characters** for sufficient utility.\n* If the document is too short, indicate how many characters it currently has and how many more are needed.\n* However, in the case of the table of contents page, it is free from the volume limit.\n* Rather than simply telling them to increase the text, **compare the number of headings to the text length**,\n and if they want to double the amount, **instruct them to do so accordingly.**\n* When referencing something from the table of contents, clearly **state the name of the section**.\n\n---\n\n# Q\\&A Guidelines\n\n* If the analyze agent asks a question, **the reviewer must answer on behalf of the user.**\n* **Never ask any questions.**\n* **Only give commands.**\n\n---\n\n# Guidelines for Hyperlinks\n\n* Even if the document is high quality, if it contains **incomplete hyperlinks**, the document is considered **incomplete**.\n* If a hyperlink points to **content that is not yet written**, the document is **incomplete regardless of quality**.\n* Instruct the analyze agent to **create a new section with the same title as the hyperlink** and\n **add it under the appropriate heading** in the document.\n* If a hyperlink points to a document outside the current page, and the current document is not a table of contents page starting with `00`, \n **instruct the planner to clear all content and rewrite the document.**\n\n---\n\n# Review Completion Conditions\n\n* When the document is determined to be complete, clearly give the following instruction:\n **The analyze agent has a tool called 'abort,' so instruct them to call it to stop the review.**\n* This instruction must only be given **when all the following conditions are met**:\n\n * All sections listed in the table of contents are **fully written**.\n * All referenced hyperlinks are **resolved**.\n* If there are still sections to write or links unresolved,\n instruct the analyze agent to continue writing,\n including the **specific section title** and a **brief explanation** of what content is needed.\n\n---\n\n# Additional Requirements for Page-Based Work Division\n\n* Each agent must write and review **only their assigned single page** out of the total pages specified.\n* Under no circumstances should an agent request or attempt to create documents beyond their assigned page.\n* If an agent attempts to request content outside their page, immediately command them to **focus solely on the current page.**\n* All document length and content sufficiency checks and corrections must be done within the single assigned page.\n* If multiple pages exist, the total number of pages must be strictly adhered to, and no extra pages should be created.\n* This strict page-level division must be enforced to maintain clear boundaries of responsibility and simplify review workflows.\n\n---\n\n**All these guidelines must be strictly enforced during the document creation and review process. Any violations require immediate correction or rewriting commands.**"
4252
+ }, {
4253
+ type: "systemMessage",
4254
+ text: [ "Below are all of the files.", "```json", input.files, "```" ].join("\n")
4255
+ } ],
4210
4256
  tokenUsage: ctx.usage()
4211
4257
  });
4212
4258
  return agent;
4213
4259
  };
4214
4260
 
4215
4261
  const orchestrateAnalyze = ctx => async props => {
4216
- const pointer = {
4217
- value: null
4218
- };
4219
4262
  const userPlanningRequirements = props.userPlanningRequirements;
4220
4263
  if (!userPlanningRequirements) {
4221
4264
  throw new Error(`Unable to prepare a proposal because there is no user requirement`);
@@ -4228,14 +4271,65 @@ const orchestrateAnalyze = ctx => async props => {
4228
4271
  step,
4229
4272
  created_at
4230
4273
  });
4231
- const agent = new AnalyzeAgent(createReviewerAgent, ctx, pointer);
4232
- const response = await agent.conversate([ `Please write a user requirement report.`, "```json", JSON.stringify(userPlanningRequirements), "```" ].join("\n"));
4233
- if (pointer.value?.files) {
4274
+ const controller = createController({
4275
+ model: ctx.model
4276
+ });
4277
+ const agentica = new MicroAgentica({
4278
+ model: ctx.model,
4279
+ vendor: ctx.vendor,
4280
+ controllers: [ controller ],
4281
+ config: {
4282
+ locale: ctx.config?.locale,
4283
+ systemPrompt: {
4284
+ common: () => "# Overview\n\n- You are the agent that determines the form of the entire document.\n- Because the tool you have has a function to determine all file names, use this function to determine the names of all files.\n- The first page of the file must be a page containing the table of contents, and from the second page, it must be a page corresponding to each table of contents.\n- Please clarify that the name of the table of contents page is the table of contents, such as `toc` or `table of content`.\n- Each document must begin with a number in turn, such as `00`, `01`, `02`, `03`.\n- Do not include database schema document."
4285
+ }
4286
+ },
4287
+ histories: [ ...ctx.histories().filter((el => el.type === "assistantMessage" || el.type === "userMessage")) ]
4288
+ });
4289
+ agentica.on("request", (event => {
4290
+ if (event.body.tools) {
4291
+ event.body.tool_choice = "required";
4292
+ }
4293
+ }));
4294
+ const determined = await agentica.conversate([ "Design a complete list of documents for that document", "```md", userPlanningRequirements, "```" ].join("\n"));
4295
+ const lastMessage = determined[determined.length - 1];
4296
+ if (lastMessage.type === "assistantMessage") {
4297
+ const history = {
4298
+ id: v4(),
4299
+ type: "assistantMessage",
4300
+ text: lastMessage.text,
4301
+ created_at,
4302
+ completed_at: (new Date).toISOString()
4303
+ };
4304
+ ctx.dispatch({
4305
+ type: "assistantMessage",
4306
+ text: lastMessage.text,
4307
+ created_at
4308
+ });
4309
+ return history;
4310
+ }
4311
+ const described = determined.find((el => el.type === "describe"));
4312
+ const filenames = Array.from(new Set(described ? described.executes.flatMap((el => {
4313
+ if (el.protocol === "class") {
4314
+ return el.arguments.files;
4315
+ }
4316
+ return null;
4317
+ })).filter((el => el !== null)) : []));
4318
+ const pointers = await Promise.all(filenames.map((async ({filename}) => {
4319
+ const pointer = {
4320
+ value: null
4321
+ };
4322
+ const agent = new AutoBeAnalyzeAgent(AutoBeAnalyzeReviewer, ctx, pointer, filenames.map((el => el.filename)));
4323
+ await agent.conversate([ `The names of all the files are as follows: ${filenames.join(",")}`, "Assume that all files are in the same folder. Also, when pointing to the location of a file, go to the relative path.", "", `Among the various documents, the part you decided to take care of is as follows.: ${filename}`, `Only write this document named '${filename}'.`, "Never write other documents.", "", "```md", JSON.stringify(userPlanningRequirements), "```" ].join("\n"));
4324
+ return pointer;
4325
+ })));
4326
+ const files = pointers.map((pointer => pointer.value?.files ?? {})).reduce(((acc, cur) => Object.assign(acc, cur)));
4327
+ if (Object.keys(files).length) {
4234
4328
  const history = {
4235
4329
  id: v4(),
4236
4330
  type: "analyze",
4237
4331
  reason: userPlanningRequirements,
4238
- files: pointer.value.files,
4332
+ files,
4239
4333
  step,
4240
4334
  created_at,
4241
4335
  completed_at: (new Date).toISOString()
@@ -4244,7 +4338,7 @@ const orchestrateAnalyze = ctx => async props => {
4244
4338
  ctx.histories().push(history);
4245
4339
  ctx.dispatch({
4246
4340
  type: "analyzeComplete",
4247
- files: pointer.value.files,
4341
+ files,
4248
4342
  step,
4249
4343
  created_at
4250
4344
  });
@@ -4253,18 +4347,383 @@ const orchestrateAnalyze = ctx => async props => {
4253
4347
  const history = {
4254
4348
  id: v4(),
4255
4349
  type: "assistantMessage",
4256
- text: response,
4350
+ text: determined.find((el => el.type === "assistantMessage"))?.text ?? "",
4257
4351
  created_at,
4258
4352
  completed_at: (new Date).toISOString()
4259
4353
  };
4260
4354
  ctx.dispatch({
4261
4355
  type: "assistantMessage",
4262
- text: response,
4356
+ text: determined.find((el => el.type === "assistantMessage"))?.text ?? "",
4263
4357
  created_at
4264
4358
  });
4265
4359
  return history;
4266
4360
  };
4267
4361
 
4362
+ function createController(props) {
4363
+ assertSchemaModel(props.model);
4364
+ const application = collection$4[props.model];
4365
+ return {
4366
+ protocol: "class",
4367
+ name: "Planning",
4368
+ application,
4369
+ execute: {
4370
+ determine: input => input
4371
+ }
4372
+ };
4373
+ }
4374
+
4375
+ const claude$4 = {
4376
+ model: "claude",
4377
+ options: {
4378
+ reference: true,
4379
+ separate: null
4380
+ },
4381
+ functions: [ {
4382
+ name: "determine",
4383
+ parameters: {
4384
+ type: "object",
4385
+ properties: {
4386
+ files: {
4387
+ type: "array",
4388
+ items: {
4389
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4390
+ type: "object",
4391
+ properties: {
4392
+ filename: {
4393
+ title: "Filename to generate or overwrite",
4394
+ description: "Filename to generate or overwrite.",
4395
+ type: "string",
4396
+ pattern: "((.*)\\.md)$"
4397
+ }
4398
+ },
4399
+ required: [ "filename" ]
4400
+ }
4401
+ }
4402
+ },
4403
+ required: [ "files" ],
4404
+ additionalProperties: false,
4405
+ $defs: {}
4406
+ },
4407
+ output: {
4408
+ type: "object",
4409
+ properties: {
4410
+ files: {
4411
+ type: "array",
4412
+ items: {
4413
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4414
+ type: "object",
4415
+ properties: {
4416
+ filename: {
4417
+ title: "Filename to generate or overwrite",
4418
+ description: "Filename to generate or overwrite.",
4419
+ type: "string",
4420
+ pattern: "((.*)\\.md)$"
4421
+ }
4422
+ },
4423
+ required: [ "filename" ]
4424
+ }
4425
+ }
4426
+ },
4427
+ required: [ "files" ]
4428
+ },
4429
+ description: "Determining the Initial File List\n\nDesign a list of initial documents that you need to create for that\nrequirement. The list of documents is determined only by the name of the\nfile.",
4430
+ validate: (() => {
4431
+ const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
4432
+ const _io1 = input => "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename);
4433
+ const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
4434
+ path: _path + ".files",
4435
+ expected: 'Array<Pick<IFile, "filename">>',
4436
+ value: input.files
4437
+ })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
4438
+ path: _path + ".files[" + _index2 + "]",
4439
+ expected: 'Pick<IFile, "filename">',
4440
+ value: elem
4441
+ })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
4442
+ path: _path + ".files[" + _index2 + "]",
4443
+ expected: 'Pick<IFile, "filename">',
4444
+ value: elem
4445
+ }))).every((flag => flag)) || _report(_exceptionable, {
4446
+ path: _path + ".files",
4447
+ expected: 'Array<Pick<IFile, "filename">>',
4448
+ value: input.files
4449
+ }) ].every((flag => flag));
4450
+ const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename) || _report(_exceptionable, {
4451
+ path: _path + ".filename",
4452
+ expected: "`${string}.md`",
4453
+ value: input.filename
4454
+ }) ].every((flag => flag));
4455
+ const __is = input => "object" === typeof input && null !== input && _io0(input);
4456
+ let errors;
4457
+ let _report;
4458
+ return input => {
4459
+ if (false === __is(input)) {
4460
+ errors = [];
4461
+ _report = __typia_transform__validateReport._validateReport(errors);
4462
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
4463
+ path: _path + "",
4464
+ expected: "__type",
4465
+ value: input
4466
+ })) && _vo0(input, _path + "", true) || _report(true, {
4467
+ path: _path + "",
4468
+ expected: "__type",
4469
+ value: input
4470
+ }))(input, "$input", true);
4471
+ const success = 0 === errors.length;
4472
+ return success ? {
4473
+ success,
4474
+ data: input
4475
+ } : {
4476
+ success,
4477
+ errors,
4478
+ data: input
4479
+ };
4480
+ }
4481
+ return {
4482
+ success: true,
4483
+ data: input
4484
+ };
4485
+ };
4486
+ })()
4487
+ } ]
4488
+ };
4489
+
4490
+ const collection$4 = {
4491
+ chatgpt: {
4492
+ model: "chatgpt",
4493
+ options: {
4494
+ reference: true,
4495
+ strict: false,
4496
+ separate: null
4497
+ },
4498
+ functions: [ {
4499
+ name: "determine",
4500
+ parameters: {
4501
+ type: "object",
4502
+ properties: {
4503
+ files: {
4504
+ type: "array",
4505
+ items: {
4506
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4507
+ type: "object",
4508
+ properties: {
4509
+ filename: {
4510
+ title: "Filename to generate or overwrite",
4511
+ description: "Filename to generate or overwrite.\n\n\n@pattern ((.*)\\.md)$",
4512
+ type: "string"
4513
+ }
4514
+ },
4515
+ required: [ "filename" ]
4516
+ }
4517
+ }
4518
+ },
4519
+ required: [ "files" ],
4520
+ additionalProperties: false,
4521
+ $defs: {}
4522
+ },
4523
+ output: {
4524
+ type: "object",
4525
+ properties: {
4526
+ files: {
4527
+ type: "array",
4528
+ items: {
4529
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4530
+ type: "object",
4531
+ properties: {
4532
+ filename: {
4533
+ title: "Filename to generate or overwrite",
4534
+ description: "Filename to generate or overwrite.\n\n\n@pattern ((.*)\\.md)$",
4535
+ type: "string"
4536
+ }
4537
+ },
4538
+ required: [ "filename" ]
4539
+ }
4540
+ }
4541
+ },
4542
+ required: [ "files" ]
4543
+ },
4544
+ description: "Determining the Initial File List\n\nDesign a list of initial documents that you need to create for that\nrequirement. The list of documents is determined only by the name of the\nfile.",
4545
+ validate: (() => {
4546
+ const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
4547
+ const _io1 = input => "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename);
4548
+ const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
4549
+ path: _path + ".files",
4550
+ expected: 'Array<Pick<IFile, "filename">>',
4551
+ value: input.files
4552
+ })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
4553
+ path: _path + ".files[" + _index2 + "]",
4554
+ expected: 'Pick<IFile, "filename">',
4555
+ value: elem
4556
+ })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
4557
+ path: _path + ".files[" + _index2 + "]",
4558
+ expected: 'Pick<IFile, "filename">',
4559
+ value: elem
4560
+ }))).every((flag => flag)) || _report(_exceptionable, {
4561
+ path: _path + ".files",
4562
+ expected: 'Array<Pick<IFile, "filename">>',
4563
+ value: input.files
4564
+ }) ].every((flag => flag));
4565
+ const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename) || _report(_exceptionable, {
4566
+ path: _path + ".filename",
4567
+ expected: "`${string}.md`",
4568
+ value: input.filename
4569
+ }) ].every((flag => flag));
4570
+ const __is = input => "object" === typeof input && null !== input && _io0(input);
4571
+ let errors;
4572
+ let _report;
4573
+ return input => {
4574
+ if (false === __is(input)) {
4575
+ errors = [];
4576
+ _report = __typia_transform__validateReport._validateReport(errors);
4577
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
4578
+ path: _path + "",
4579
+ expected: "__type",
4580
+ value: input
4581
+ })) && _vo0(input, _path + "", true) || _report(true, {
4582
+ path: _path + "",
4583
+ expected: "__type",
4584
+ value: input
4585
+ }))(input, "$input", true);
4586
+ const success = 0 === errors.length;
4587
+ return success ? {
4588
+ success,
4589
+ data: input
4590
+ } : {
4591
+ success,
4592
+ errors,
4593
+ data: input
4594
+ };
4595
+ }
4596
+ return {
4597
+ success: true,
4598
+ data: input
4599
+ };
4600
+ };
4601
+ })()
4602
+ } ]
4603
+ },
4604
+ claude: claude$4,
4605
+ llama: claude$4,
4606
+ deepseek: claude$4,
4607
+ 3.1: claude$4,
4608
+ "3.0": {
4609
+ model: "3.0",
4610
+ options: {
4611
+ constraint: true,
4612
+ recursive: 3,
4613
+ separate: null
4614
+ },
4615
+ functions: [ {
4616
+ name: "determine",
4617
+ parameters: {
4618
+ type: "object",
4619
+ properties: {
4620
+ files: {
4621
+ type: "array",
4622
+ items: {
4623
+ type: "object",
4624
+ properties: {
4625
+ filename: {
4626
+ type: "string",
4627
+ pattern: "((.*)\\.md)$",
4628
+ title: "Filename to generate or overwrite",
4629
+ description: "Filename to generate or overwrite."
4630
+ }
4631
+ },
4632
+ required: [ "filename" ],
4633
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4634
+ additionalProperties: false
4635
+ }
4636
+ }
4637
+ },
4638
+ required: [ "files" ],
4639
+ additionalProperties: false
4640
+ },
4641
+ output: {
4642
+ type: "object",
4643
+ properties: {
4644
+ files: {
4645
+ type: "array",
4646
+ items: {
4647
+ type: "object",
4648
+ properties: {
4649
+ filename: {
4650
+ type: "string",
4651
+ pattern: "((.*)\\.md)$",
4652
+ title: "Filename to generate or overwrite",
4653
+ description: "Filename to generate or overwrite."
4654
+ }
4655
+ },
4656
+ required: [ "filename" ],
4657
+ description: "Description of the current {@link PickIFilefilename} type:\n\n> From T, pick a set of properties whose keys are in the union K",
4658
+ additionalProperties: false
4659
+ }
4660
+ }
4661
+ },
4662
+ required: [ "files" ],
4663
+ additionalProperties: false
4664
+ },
4665
+ description: "Determining the Initial File List\n\nDesign a list of initial documents that you need to create for that\nrequirement. The list of documents is determined only by the name of the\nfile.",
4666
+ validate: (() => {
4667
+ const _io0 = input => Array.isArray(input.files) && input.files.every((elem => "object" === typeof elem && null !== elem && _io1(elem)));
4668
+ const _io1 = input => "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename);
4669
+ const _vo0 = (input, _path, _exceptionable = true) => [ (Array.isArray(input.files) || _report(_exceptionable, {
4670
+ path: _path + ".files",
4671
+ expected: 'Array<Pick<IFile, "filename">>',
4672
+ value: input.files
4673
+ })) && input.files.map(((elem, _index2) => ("object" === typeof elem && null !== elem || _report(_exceptionable, {
4674
+ path: _path + ".files[" + _index2 + "]",
4675
+ expected: 'Pick<IFile, "filename">',
4676
+ value: elem
4677
+ })) && _vo1(elem, _path + ".files[" + _index2 + "]", _exceptionable) || _report(_exceptionable, {
4678
+ path: _path + ".files[" + _index2 + "]",
4679
+ expected: 'Pick<IFile, "filename">',
4680
+ value: elem
4681
+ }))).every((flag => flag)) || _report(_exceptionable, {
4682
+ path: _path + ".files",
4683
+ expected: 'Array<Pick<IFile, "filename">>',
4684
+ value: input.files
4685
+ }) ].every((flag => flag));
4686
+ const _vo1 = (input, _path, _exceptionable = true) => [ "string" === typeof input.filename && RegExp(/(.*)\.md$/).test(input.filename) || _report(_exceptionable, {
4687
+ path: _path + ".filename",
4688
+ expected: "`${string}.md`",
4689
+ value: input.filename
4690
+ }) ].every((flag => flag));
4691
+ const __is = input => "object" === typeof input && null !== input && _io0(input);
4692
+ let errors;
4693
+ let _report;
4694
+ return input => {
4695
+ if (false === __is(input)) {
4696
+ errors = [];
4697
+ _report = __typia_transform__validateReport._validateReport(errors);
4698
+ ((input, _path, _exceptionable = true) => ("object" === typeof input && null !== input || _report(true, {
4699
+ path: _path + "",
4700
+ expected: "__type",
4701
+ value: input
4702
+ })) && _vo0(input, _path + "", true) || _report(true, {
4703
+ path: _path + "",
4704
+ expected: "__type",
4705
+ value: input
4706
+ }))(input, "$input", true);
4707
+ const success = 0 === errors.length;
4708
+ return success ? {
4709
+ success,
4710
+ data: input
4711
+ } : {
4712
+ success,
4713
+ errors,
4714
+ data: input
4715
+ };
4716
+ }
4717
+ return {
4718
+ success: true,
4719
+ data: input
4720
+ };
4721
+ };
4722
+ })()
4723
+ } ]
4724
+ }
4725
+ };
4726
+
4268
4727
  const orchestrateRealize = ctx => async props => null;
4269
4728
 
4270
4729
  const orchestrateTest = ctx => async props => null;
@@ -8422,7 +8881,7 @@ const orchestratePrisma = ctx => async props => {
8422
8881
  };
8423
8882
  ctx.state().prisma = history;
8424
8883
  ctx.histories().push(history);
8425
- if (history.result.success === true && history.compiled.type === "success") ctx.dispatch({
8884
+ if (history.result.success === true) ctx.dispatch({
8426
8885
  type: "prismaComplete",
8427
8886
  application: history.result.data,
8428
8887
  schemas: history.schemas,