@deepagents/orchestrator 7.0.2 → 7.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/lib/arxiv/arxiv.d.ts +9 -3
- package/dist/lib/arxiv/arxiv.d.ts.map +1 -1
- package/dist/lib/arxiv/arxiv.js +3 -11
- package/dist/lib/arxiv/arxiv.js.map +2 -2
- package/dist/lib/citation.js +3 -6
- package/dist/lib/citation.js.map +2 -2
- package/dist/lib/deepplan/demo.js.map +1 -1
- package/dist/lib/deepplan/executors/research-executor.js.map +2 -2
- package/dist/lib/deepplan/plan-and-solve.js +2 -6
- package/dist/lib/deepplan/plan-and-solve.js.map +2 -2
- package/dist/lib/deepplan/planner-agent.d.ts.map +1 -1
- package/dist/lib/deepplan/planner-agent.js +1 -4
- package/dist/lib/deepplan/planner-agent.js.map +2 -2
- package/dist/lib/deepplan/replanner-agent.d.ts.map +1 -1
- package/dist/lib/deepplan/replanner-agent.js +1 -2
- package/dist/lib/deepplan/replanner-agent.js.map +2 -2
- package/dist/lib/deepresearch.v0.d.ts.map +1 -1
- package/dist/lib/deepresearch.v0.js +21 -18
- package/dist/lib/deepresearch.v0.js.map +2 -2
- package/dist/lib/deepresearch.v1.d.ts.map +1 -1
- package/dist/lib/deepresearch.v1.js +3 -5
- package/dist/lib/deepresearch.v1.js.map +2 -2
- package/dist/lib/deepwiki/complete-wiki.js +4 -2
- package/dist/lib/deepwiki/complete-wiki.js.map +2 -2
- package/dist/lib/deepwiki/deepwiki.js +4 -2
- package/dist/lib/deepwiki/deepwiki.js.map +2 -2
- package/dist/lib/deepwiki/gitignore-agent.d.ts +4 -2
- package/dist/lib/deepwiki/gitignore-agent.d.ts.map +1 -1
- package/dist/lib/deepwiki/gitignore-agent.js +2 -3
- package/dist/lib/deepwiki/gitignore-agent.js.map +2 -2
- package/dist/lib/deepwiki/outline-agent.d.ts.map +1 -1
- package/dist/lib/deepwiki/outline-agent.js +4 -2
- package/dist/lib/deepwiki/outline-agent.js.map +2 -2
- package/dist/lib/deepwiki/wiki-writer.js +4 -2
- package/dist/lib/deepwiki/wiki-writer.js.map +2 -2
- package/dist/lib/deepwiki/writer.d.ts.map +1 -1
- package/dist/lib/deepwiki/writer.js +5 -5
- package/dist/lib/deepwiki/writer.js.map +2 -2
- package/dist/lib/evolving.js +1 -1
- package/dist/lib/evolving.js.map +2 -2
- package/dist/lib/openai-deepresearch/clarrify-agent.d.ts +5 -1
- package/dist/lib/openai-deepresearch/clarrify-agent.d.ts.map +1 -1
- package/dist/lib/openai-deepresearch/lead-research.d.ts.map +1 -1
- package/dist/lib/openai-deepresearch/lead-research.js +2 -3
- package/dist/lib/openai-deepresearch/lead-research.js.map +2 -2
- package/dist/lib/openai-deepresearch/openai-deepresearch.js +6 -8
- package/dist/lib/openai-deepresearch/openai-deepresearch.js.map +3 -3
- package/dist/lib/openai-deepresearch/reasearcher.js.map +2 -2
- package/dist/lib/openai-deepresearch/research-brief.d.ts +3 -1
- package/dist/lib/openai-deepresearch/research-brief.d.ts.map +1 -1
- package/package.json +5 -5
|
@@ -72,9 +72,8 @@ Repository Context Summary:
|
|
|
72
72
|
${repoContext}`,
|
|
73
73
|
{}
|
|
74
74
|
);
|
|
75
|
-
const result = output;
|
|
76
75
|
return uniqBy(
|
|
77
|
-
|
|
76
|
+
output.items.map((s) => s.trim()).filter(Boolean),
|
|
78
77
|
(s) => s.toLowerCase()
|
|
79
78
|
);
|
|
80
79
|
}
|
|
@@ -108,8 +107,11 @@ ${repoContext}
|
|
|
108
107
|
|
|
109
108
|
Based on the above information, determine if further research is needed. If yes, provide up to four new search queries. If the research is complete and sufficient, indicate that no more research is needed.`;
|
|
110
109
|
try {
|
|
111
|
-
const { output } = await generate(
|
|
112
|
-
|
|
110
|
+
const { output: result } = await generate(
|
|
111
|
+
newSearchQueriesAgent,
|
|
112
|
+
prompt,
|
|
113
|
+
{}
|
|
114
|
+
);
|
|
113
115
|
if (!result.needsMoreResearch) {
|
|
114
116
|
console.log(
|
|
115
117
|
"Research assessment: No further research needed.",
|
|
@@ -149,8 +151,7 @@ ${pageText}
|
|
|
149
151
|
|
|
150
152
|
Decide if the page is useful.`;
|
|
151
153
|
const { output } = await generate(pageUsefulnessAgent, prompt, {});
|
|
152
|
-
|
|
153
|
-
return result.answer === "Yes";
|
|
154
|
+
return output.answer === "Yes";
|
|
154
155
|
}
|
|
155
156
|
async function extractRelevantContext(userQuery, searchQuery, pageText) {
|
|
156
157
|
const prompt = `User Query: ${userQuery}
|
|
@@ -240,14 +241,17 @@ if (import.meta.main) {
|
|
|
240
241
|
const iterLimit = 2;
|
|
241
242
|
const aggregatedContexts = [];
|
|
242
243
|
const allSearchQueries = [];
|
|
243
|
-
let iteration = 0;
|
|
244
244
|
const repoContext = await gatherRepoContext();
|
|
245
|
-
|
|
245
|
+
const initialSearchQueries = await generateSearchQueries(
|
|
246
|
+
userQuery,
|
|
247
|
+
repoContext
|
|
248
|
+
);
|
|
246
249
|
const performSearch = search();
|
|
247
|
-
|
|
250
|
+
const research = async (searchQueries, iteration) => {
|
|
251
|
+
if (iteration >= iterLimit) return;
|
|
248
252
|
const iterationContexts = [];
|
|
249
|
-
allSearchQueries.push(...
|
|
250
|
-
const searchResults = await performSearch(
|
|
253
|
+
allSearchQueries.push(...searchQueries);
|
|
254
|
+
const searchResults = await performSearch(searchQueries);
|
|
251
255
|
await Promise.all(
|
|
252
256
|
Object.entries(searchResults).map(async ([source, query]) => {
|
|
253
257
|
const context = await processFile(source, userQuery, query);
|
|
@@ -267,20 +271,19 @@ Content: ${context.content}
|
|
|
267
271
|
} else {
|
|
268
272
|
aggregatedContexts.push(...iterationContexts);
|
|
269
273
|
}
|
|
270
|
-
|
|
274
|
+
const newSearchQueries = await getNewSearchQueries(
|
|
271
275
|
userQuery,
|
|
272
276
|
allSearchQueries,
|
|
273
277
|
aggregatedContexts,
|
|
274
278
|
repoContext
|
|
275
279
|
);
|
|
276
|
-
if (
|
|
280
|
+
if (newSearchQueries.length === 0) {
|
|
277
281
|
console.log("No further research needed. Exiting loop.");
|
|
278
|
-
|
|
279
|
-
} else {
|
|
280
|
-
allSearchQueries.push(...searchQueriesResult);
|
|
282
|
+
return;
|
|
281
283
|
}
|
|
282
|
-
iteration
|
|
283
|
-
}
|
|
284
|
+
await research(newSearchQueries, iteration + 1);
|
|
285
|
+
};
|
|
286
|
+
await research(initialSearchQueries, 0);
|
|
284
287
|
console.log("\nGenerating final report...");
|
|
285
288
|
console.log("Search queries performed:", allSearchQueries);
|
|
286
289
|
const finalReport = await generateFinalReport(
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/deepresearch.v0.ts"],
|
|
4
|
-
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { openai } from '@ai-sdk/openai';\nimport { uniqBy } from 'lodash-es';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport z from 'zod';\n\nimport { agent, execute, generate, lmstudio } from '@deepagents/agent';\nimport { fastembed, nodeSQLite, similaritySearch } from '@deepagents/retrieval';\nimport * as connectors from '@deepagents/retrieval/connectors';\n\nconst searchQueryAgent = agent({\n name: 'search-query-generator',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n `You are an expert research assistant. Given the user's query, generate up to four distinct, precise SEMANTIC search queries well-suited for a vector database of repository content (code, docs, comments).`,\n `Rules: (1) Do NOT include file paths, globs, regex, repository names, or line numbers. (2) Avoid repeating the same idea; ensure diversity (architecture, data flow, services, APIs, domain terms). (3) Keep each query concise (3\u201310 words). (4) Prefer concept-level phrasing over filenames.`,\n 'Return only the queries as plain strings; no numbering or extra commentary.',\n ],\n output: z.object({ items: z.array(z.string()).max(4) }),\n});\n\nconst repoContextAgent = agent({\n name: 'repo-context-summarizer',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You are an expert codebase analyst. You will receive samples from a repository (file paths with short content snippets).',\n 'Produce a concise context summary capturing: primary domains, major modules/components, key data models, important services/APIs, external integrations, and notable terminology or patterns.',\n 'Format as short markdown sections with bullet points. Keep under 400 words. Do not speculate beyond the provided snippets.',\n ],\n});\n\nconst newSearchQueriesAgent = agent({\n name: 'research-continuation-planner',\n model: groq('openai/gpt-oss-120b'),\n prompt:\n 'You are an analytical research assistant. Based on the original query, the search queries performed so far, and the extracted contexts, determine if further research is needed.',\n output: z.object({\n needsMoreResearch: z\n .boolean()\n .describe('Whether additional research is needed'),\n newQueries: z\n .array(z.string())\n .max(4)\n .describe(\n 'Up to four new search queries if more research is needed, empty array otherwise',\n ),\n reasoning: z\n .string()\n .optional()\n .describe('Brief explanation of the decision'),\n }),\n});\n\nconst pageUsefulnessAgent = agent({\n name: 'page-usefulness-evaluator',\n model: lmstudio('qwen/qwen3-4b-2507'),\n prompt: [\n 'You are a strict and concise evaluator of research relevance.',\n \"Given the user's query and the content of a repository file, determine if the file contains information relevant and useful for addressing the query.\",\n \"Respond with exactly one word: 'Yes' if the file is useful, or 'No' if it is not.\",\n ],\n output: z.object({ answer: z.enum(['Yes', 'No']) }),\n});\n\nconst extractRelevantContextAgent = agent({\n name: 'relevant-context-extractor',\n model: groq('openai/gpt-oss-20b'),\n\n prompt: [\n 'You are an expert in extracting and summarizing relevant information.',\n \"Given the user's query, the search query that led to this page, and the file content, extract all pieces of information that are relevant to answering the user's query.\",\n 'Return only the relevant context as plain text without commentary.',\n ],\n});\n\nconst finalReportAgent = agent({\n name: 'final-report-writer',\n model: openai('gpt-4.1'),\n prompt: `You are an expert product manager that is working on reversing existing product to user stories based on a developer question/inquiry. Based on the gathered contexts below and the original query, write a comprehensive, well-structured, and detailed report that addresses the query thoroughly.\\nInclude all relevant insights and conclusions without extraneous commentary.`,\n});\n\nasync function generateSearchQueries(\n input: string,\n repoContext: string,\n): Promise<string[]> {\n const { output } = await generate(\n searchQueryAgent,\n `User Query: ${input}\\n\\nRepository Context Summary:\\n${repoContext}`,\n {},\n );\n const result = output as { items?: string[] };\n return uniqBy(\n (result.items ?? []).map((s: string) => s.trim()).filter(Boolean),\n (s: string) => s.toLowerCase(),\n );\n}\n\nasync function retrieve(query: string) {\n const results = await similaritySearch(query, {\n connector: connectors.repo(\n '/Users/ezzabuzaid/Desktop/mo/virtual-care',\n ['.ts', '.tsx', '.md', '.prisma'],\n 'never',\n ),\n store: nodeSQLite('deepsearch.sqlite', 384),\n embedder: fastembed(),\n });\n return results.map((it) => ({\n snippet: it.content,\n source: it.document_id,\n similarity: it.similarity,\n }));\n}\n\nexport async function getNewSearchQueries(\n userQuery: string,\n previousSearchQueries: string[],\n allContexts: string[],\n repoContext: string,\n): Promise<string[]> {\n const contextCombined = allContexts.join('\\n\\n');\n const prompt = `User Query: ${userQuery}\n\nPrevious Search Queries: ${JSON.stringify(previousSearchQueries)}\n\nExtracted Relevant Contexts:\n${contextCombined}\n\nRepository Context Summary:\n${repoContext}\n\nBased on the above information, determine if further research is needed. If yes, provide up to four new search queries. If the research is complete and sufficient, indicate that no more research is needed.`;\n\n try {\n const { output } = await generate(newSearchQueriesAgent, prompt, {});\n const result = output as {\n needsMoreResearch: boolean;\n newQueries: string[];\n reasoning?: string;\n };\n\n if (!result.needsMoreResearch) {\n console.log(\n 'Research assessment: No further research needed.',\n result.reasoning,\n );\n return [];\n }\n\n console.log(\n `Research assessment: ${result.newQueries.length} new queries generated.`,\n result.reasoning,\n );\n return uniqBy(\n result.newQueries.map((s: string) => s.trim()).filter(Boolean),\n (s: string) => s.toLowerCase(),\n );\n } catch (error) {\n console.error('Error generating new search queries:', error);\n return [];\n }\n}\n\nexport async function generateFinalReport(\n userQuery: string,\n formatting: string,\n allContexts: string[],\n): Promise<string> {\n const contextCombined = allContexts.join('\\n\\n');\n const prompt = `\nDeveloper Query: ${userQuery}\nFormatting: ${formatting}\n\nGathered Relevant Contexts:\n${contextCombined}`;\n\n return (await execute(finalReportAgent, prompt, {})).text;\n}\n\nasync function isPageUseful(userQuery: string, pageText: string) {\n const prompt = `User Query: ${userQuery}\\n\\nRepo file content\\n\\n${pageText}\\n\\nDecide if the page is useful.`;\n const { output } = await generate(pageUsefulnessAgent, prompt, {} as const);\n const result = output as { answer: 'Yes' | 'No' };\n return result.answer === 'Yes';\n}\n\nasync function extractRelevantContext(\n userQuery: string,\n searchQuery: string,\n pageText: string,\n): Promise<string> {\n const prompt = `User Query: ${userQuery}\\nSearch Query: ${searchQuery}\\n\\nRepo file content\\n\\n${pageText}\\n\\nExtract the relevant context.`;\n return (await execute(extractRelevantContextAgent, prompt, {} as const)).text;\n}\n\nasync function processFile(\n filePath: string,\n userQuery: string,\n searchQuery: string,\n): Promise<{ source: string; content: string } | null> {\n const content = await readFile(filePath, 'utf-8');\n const useful = await isPageUseful(userQuery, content);\n if (useful) {\n return {\n source: filePath,\n content: await extractRelevantContext(userQuery, searchQuery, content),\n };\n }\n return null;\n}\n\nasync function gatherRepoContext(): Promise<string> {\n const seeds = [\n 'project overview',\n 'backend',\n 'framework',\n 'hono express',\n 'architecture',\n 'services',\n 'prisma',\n 'database',\n 'data model',\n 'payments',\n 'billing',\n ];\n const results = await Promise.all(seeds.map((it) => retrieve(it)));\n const deduped = uniqBy(results.flat(), (it) => it.source);\n const bundle = deduped\n .map((r, i) => `(${i + 1}) Path: ${r.source}\\nSnippet:\\n${r.snippet}`)\n .join('\\n\\n---\\n\\n');\n\n const summary = (\n await execute(\n repoContextAgent,\n `Repository Samples (path + snippet):\\n\\n${bundle}\\n\\nSummarize as requested.`,\n {},\n )\n ).text;\n return summary;\n}\n\nfunction search() {\n const cache: Record<string, Awaited<ReturnType<typeof retrieve>>> = {};\n const processedSources = new Set<string>();\n return async (queries: string[]) => {\n const results: Awaited<ReturnType<typeof retrieve>>[] = [];\n for (const query of queries) {\n if (!cache[query]) {\n const res = await retrieve(query);\n cache[query] = uniqBy(res, (it) => it.source);\n }\n results.push(cache[query]);\n }\n const uniqueLinks: Record<string, string> = {};\n for (let i = 0; i < results.length; i++) {\n const query = queries[i];\n for (const item of results[i]) {\n if (!uniqueLinks[item.source] && !processedSources.has(item.source)) {\n uniqueLinks[item.source] = query;\n processedSources.add(item.source);\n }\n }\n }\n return uniqueLinks;\n };\n}\n\nif (import.meta.main) {\n const userQuery = 'How do we process payment?';\n\n const formatting = `\n1. use ascii markdown diagrams to illustrate. I am visual learner and I love markdown.\n2. use \"user stories\" to illustrate flows. we are not looking for only text or techical explanation.\n3. user story scenario should be divided by actors and steps.\n4. when referencing code snippets, include file path.\n`;\n\n const iterLimit = 2;\n const aggregatedContexts: string[] = [];\n const allSearchQueries: string[] = [];\n let iteration = 0;\n const repoContext = await gatherRepoContext();\n let searchQueriesResult = await generateSearchQueries(userQuery, repoContext);\n const performSearch = search();\n\n while (iteration < iterLimit) {\n const iterationContexts: string[] = [];\n\n allSearchQueries.push(...searchQueriesResult);\n const searchResults = await performSearch(searchQueriesResult);\n\n await Promise.all(\n Object.entries(searchResults).map(async ([source, query]) => {\n const context = await processFile(source, userQuery, query);\n if (context) {\n iterationContexts.push(\n `Source: ${context.source}\\n\\nContent: ${context.content}\\n\\n`,\n );\n }\n }),\n );\n\n if (iterationContexts.length === 0) {\n console.log('No useful contexts were found in this iteration.');\n } else {\n aggregatedContexts.push(...iterationContexts);\n }\n\n searchQueriesResult = await getNewSearchQueries(\n userQuery,\n allSearchQueries,\n aggregatedContexts,\n repoContext,\n );\n if (searchQueriesResult.length === 0) {\n console.log('No further research needed. Exiting loop.');\n break;\n } else {\n allSearchQueries.push(...searchQueriesResult);\n }\n\n iteration += 1;\n }\n\n console.log('\\nGenerating final report...');\n console.log('Search queries performed:', allSearchQueries);\n const finalReport = await generateFinalReport(\n userQuery,\n formatting,\n aggregatedContexts,\n );\n\n await writeFile('final_report.md', finalReport);\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,UAAU,iBAAiB;AACpC,OAAO,OAAO;AAEd,SAAS,OAAO,SAAS,UAAU,gBAAgB;AACnD,SAAS,WAAW,YAAY,wBAAwB;AACxD,YAAY,gBAAgB;AAE5B,IAAM,mBAAmB,MAAM;AAAA,EAC7B,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAChC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,IAAI,CAAC,EAAE,CAAC;AACxD,CAAC;AAED,IAAM,mBAAmB,MAAM;AAAA,EAC7B,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAChC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,CAAC;AAED,IAAM,wBAAwB,MAAM;AAAA,EAClC,MAAM;AAAA,EACN,OAAO,KAAK,qBAAqB;AAAA,EACjC,QACE;AAAA,EACF,QAAQ,EAAE,OAAO;AAAA,IACf,mBAAmB,EAChB,QAAQ,EACR,SAAS,uCAAuC;AAAA,IACnD,YAAY,EACT,MAAM,EAAE,OAAO,CAAC,EAChB,IAAI,CAAC,EACL;AAAA,MACC;AAAA,IACF;AAAA,IACF,WAAW,EACR,OAAO,EACP,SAAS,EACT,SAAS,mCAAmC;AAAA,EACjD,CAAC;AACH,CAAC;AAED,IAAM,sBAAsB,MAAM;AAAA,EAChC,MAAM;AAAA,EACN,OAAO,SAAS,oBAAoB;AAAA,EACpC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ,EAAE,OAAO,EAAE,QAAQ,EAAE,KAAK,CAAC,OAAO,IAAI,CAAC,EAAE,CAAC;AACpD,CAAC;AAED,IAAM,8BAA8B,MAAM;AAAA,EACxC,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAEhC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AACF,CAAC;AAED,IAAM,mBAAmB,MAAM;AAAA,EAC7B,MAAM;AAAA,EACN,OAAO,OAAO,SAAS;AAAA,EACvB,QAAQ;AAAA;AACV,CAAC;AAED,eAAe,sBACb,OACA,aACmB;AACnB,QAAM,EAAE,OAAO,IAAI,MAAM;AAAA,IACvB;AAAA,IACA,eAAe,KAAK;AAAA;AAAA;AAAA,EAAoC,WAAW;AAAA,IACnE,CAAC;AAAA,EACH;AACA,
|
|
4
|
+
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { openai } from '@ai-sdk/openai';\nimport { uniqBy } from 'lodash-es';\nimport { readFile, writeFile } from 'node:fs/promises';\nimport z from 'zod';\n\nimport { agent, execute, generate, lmstudio } from '@deepagents/agent';\nimport { fastembed, nodeSQLite, similaritySearch } from '@deepagents/retrieval';\nimport * as connectors from '@deepagents/retrieval/connectors';\n\nconst searchQueryAgent = agent({\n name: 'search-query-generator',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n `You are an expert research assistant. Given the user's query, generate up to four distinct, precise SEMANTIC search queries well-suited for a vector database of repository content (code, docs, comments).`,\n `Rules: (1) Do NOT include file paths, globs, regex, repository names, or line numbers. (2) Avoid repeating the same idea; ensure diversity (architecture, data flow, services, APIs, domain terms). (3) Keep each query concise (3\u201310 words). (4) Prefer concept-level phrasing over filenames.`,\n 'Return only the queries as plain strings; no numbering or extra commentary.',\n ],\n output: z.object({ items: z.array(z.string()).max(4) }),\n});\n\nconst repoContextAgent = agent({\n name: 'repo-context-summarizer',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You are an expert codebase analyst. You will receive samples from a repository (file paths with short content snippets).',\n 'Produce a concise context summary capturing: primary domains, major modules/components, key data models, important services/APIs, external integrations, and notable terminology or patterns.',\n 'Format as short markdown sections with bullet points. Keep under 400 words. Do not speculate beyond the provided snippets.',\n ],\n});\n\nconst newSearchQueriesAgent = agent({\n name: 'research-continuation-planner',\n model: groq('openai/gpt-oss-120b'),\n prompt:\n 'You are an analytical research assistant. Based on the original query, the search queries performed so far, and the extracted contexts, determine if further research is needed.',\n output: z.object({\n needsMoreResearch: z\n .boolean()\n .describe('Whether additional research is needed'),\n newQueries: z\n .array(z.string())\n .max(4)\n .describe(\n 'Up to four new search queries if more research is needed, empty array otherwise',\n ),\n reasoning: z\n .string()\n .optional()\n .describe('Brief explanation of the decision'),\n }),\n});\n\nconst pageUsefulnessAgent = agent({\n name: 'page-usefulness-evaluator',\n model: lmstudio('qwen/qwen3-4b-2507'),\n prompt: [\n 'You are a strict and concise evaluator of research relevance.',\n \"Given the user's query and the content of a repository file, determine if the file contains information relevant and useful for addressing the query.\",\n \"Respond with exactly one word: 'Yes' if the file is useful, or 'No' if it is not.\",\n ],\n output: z.object({ answer: z.enum(['Yes', 'No']) }),\n});\n\nconst extractRelevantContextAgent = agent({\n name: 'relevant-context-extractor',\n model: groq('openai/gpt-oss-20b'),\n\n prompt: [\n 'You are an expert in extracting and summarizing relevant information.',\n \"Given the user's query, the search query that led to this page, and the file content, extract all pieces of information that are relevant to answering the user's query.\",\n 'Return only the relevant context as plain text without commentary.',\n ],\n});\n\nconst finalReportAgent = agent({\n name: 'final-report-writer',\n model: openai('gpt-4.1'),\n prompt: `You are an expert product manager that is working on reversing existing product to user stories based on a developer question/inquiry. Based on the gathered contexts below and the original query, write a comprehensive, well-structured, and detailed report that addresses the query thoroughly.\\nInclude all relevant insights and conclusions without extraneous commentary.`,\n});\n\nasync function generateSearchQueries(\n input: string,\n repoContext: string,\n): Promise<string[]> {\n const { output } = await generate(\n searchQueryAgent,\n `User Query: ${input}\\n\\nRepository Context Summary:\\n${repoContext}`,\n {},\n );\n return uniqBy(\n output.items.map((s: string) => s.trim()).filter(Boolean),\n (s: string) => s.toLowerCase(),\n );\n}\n\nasync function retrieve(query: string) {\n const results = await similaritySearch(query, {\n connector: connectors.repo(\n '/Users/ezzabuzaid/Desktop/mo/virtual-care',\n ['.ts', '.tsx', '.md', '.prisma'],\n 'never',\n ),\n store: nodeSQLite('deepsearch.sqlite', 384),\n embedder: fastembed(),\n });\n return results.map((it) => ({\n snippet: it.content,\n source: it.document_id,\n similarity: it.similarity,\n }));\n}\n\nexport async function getNewSearchQueries(\n userQuery: string,\n previousSearchQueries: string[],\n allContexts: string[],\n repoContext: string,\n): Promise<string[]> {\n const contextCombined = allContexts.join('\\n\\n');\n const prompt = `User Query: ${userQuery}\n\nPrevious Search Queries: ${JSON.stringify(previousSearchQueries)}\n\nExtracted Relevant Contexts:\n${contextCombined}\n\nRepository Context Summary:\n${repoContext}\n\nBased on the above information, determine if further research is needed. If yes, provide up to four new search queries. If the research is complete and sufficient, indicate that no more research is needed.`;\n\n try {\n const { output: result } = await generate(\n newSearchQueriesAgent,\n prompt,\n {},\n );\n\n if (!result.needsMoreResearch) {\n console.log(\n 'Research assessment: No further research needed.',\n result.reasoning,\n );\n return [];\n }\n\n console.log(\n `Research assessment: ${result.newQueries.length} new queries generated.`,\n result.reasoning,\n );\n return uniqBy(\n result.newQueries.map((s: string) => s.trim()).filter(Boolean),\n (s: string) => s.toLowerCase(),\n );\n } catch (error) {\n console.error('Error generating new search queries:', error);\n return [];\n }\n}\n\nexport async function generateFinalReport(\n userQuery: string,\n formatting: string,\n allContexts: string[],\n): Promise<string> {\n const contextCombined = allContexts.join('\\n\\n');\n const prompt = `\nDeveloper Query: ${userQuery}\nFormatting: ${formatting}\n\nGathered Relevant Contexts:\n${contextCombined}`;\n\n return (await execute(finalReportAgent, prompt, {})).text;\n}\n\nasync function isPageUseful(userQuery: string, pageText: string) {\n const prompt = `User Query: ${userQuery}\\n\\nRepo file content\\n\\n${pageText}\\n\\nDecide if the page is useful.`;\n const { output } = await generate(pageUsefulnessAgent, prompt, {} as const);\n return output.answer === 'Yes';\n}\n\nasync function extractRelevantContext(\n userQuery: string,\n searchQuery: string,\n pageText: string,\n): Promise<string> {\n const prompt = `User Query: ${userQuery}\\nSearch Query: ${searchQuery}\\n\\nRepo file content\\n\\n${pageText}\\n\\nExtract the relevant context.`;\n return (await execute(extractRelevantContextAgent, prompt, {} as const)).text;\n}\n\nasync function processFile(\n filePath: string,\n userQuery: string,\n searchQuery: string,\n): Promise<{ source: string; content: string } | null> {\n const content = await readFile(filePath, 'utf-8');\n const useful = await isPageUseful(userQuery, content);\n if (useful) {\n return {\n source: filePath,\n content: await extractRelevantContext(userQuery, searchQuery, content),\n };\n }\n return null;\n}\n\nasync function gatherRepoContext(): Promise<string> {\n const seeds = [\n 'project overview',\n 'backend',\n 'framework',\n 'hono express',\n 'architecture',\n 'services',\n 'prisma',\n 'database',\n 'data model',\n 'payments',\n 'billing',\n ];\n const results = await Promise.all(seeds.map((it) => retrieve(it)));\n const deduped = uniqBy(results.flat(), (it) => it.source);\n const bundle = deduped\n .map((r, i) => `(${i + 1}) Path: ${r.source}\\nSnippet:\\n${r.snippet}`)\n .join('\\n\\n---\\n\\n');\n\n const summary = (\n await execute(\n repoContextAgent,\n `Repository Samples (path + snippet):\\n\\n${bundle}\\n\\nSummarize as requested.`,\n {},\n )\n ).text;\n return summary;\n}\n\nfunction search() {\n const cache: Record<string, Awaited<ReturnType<typeof retrieve>>> = {};\n const processedSources = new Set<string>();\n return async (queries: string[]) => {\n const results: Awaited<ReturnType<typeof retrieve>>[] = [];\n for (const query of queries) {\n if (!cache[query]) {\n const res = await retrieve(query);\n cache[query] = uniqBy(res, (it) => it.source);\n }\n results.push(cache[query]);\n }\n const uniqueLinks: Record<string, string> = {};\n for (let i = 0; i < results.length; i++) {\n const query = queries[i];\n for (const item of results[i]) {\n if (!uniqueLinks[item.source] && !processedSources.has(item.source)) {\n uniqueLinks[item.source] = query;\n processedSources.add(item.source);\n }\n }\n }\n return uniqueLinks;\n };\n}\n\nif (import.meta.main) {\n const userQuery = 'How do we process payment?';\n\n const formatting = `\n1. use ascii markdown diagrams to illustrate. I am visual learner and I love markdown.\n2. use \"user stories\" to illustrate flows. we are not looking for only text or techical explanation.\n3. user story scenario should be divided by actors and steps.\n4. when referencing code snippets, include file path.\n`;\n\n const iterLimit = 2;\n const aggregatedContexts: string[] = [];\n const allSearchQueries: string[] = [];\n const repoContext = await gatherRepoContext();\n const initialSearchQueries = await generateSearchQueries(\n userQuery,\n repoContext,\n );\n const performSearch = search();\n\n const research = async (\n searchQueries: string[],\n iteration: number,\n ): Promise<void> => {\n if (iteration >= iterLimit) return;\n const iterationContexts: string[] = [];\n\n allSearchQueries.push(...searchQueries);\n const searchResults = await performSearch(searchQueries);\n\n await Promise.all(\n Object.entries(searchResults).map(async ([source, query]) => {\n const context = await processFile(source, userQuery, query);\n if (context) {\n iterationContexts.push(\n `Source: ${context.source}\\n\\nContent: ${context.content}\\n\\n`,\n );\n }\n }),\n );\n\n if (iterationContexts.length === 0) {\n console.log('No useful contexts were found in this iteration.');\n } else {\n aggregatedContexts.push(...iterationContexts);\n }\n\n const newSearchQueries = await getNewSearchQueries(\n userQuery,\n allSearchQueries,\n aggregatedContexts,\n repoContext,\n );\n if (newSearchQueries.length === 0) {\n console.log('No further research needed. Exiting loop.');\n return;\n }\n\n // research() records the batch it searches.\n await research(newSearchQueries, iteration + 1);\n };\n\n await research(initialSearchQueries, 0);\n\n console.log('\\nGenerating final report...');\n console.log('Search queries performed:', allSearchQueries);\n const finalReport = await generateFinalReport(\n userQuery,\n formatting,\n aggregatedContexts,\n );\n\n await writeFile('final_report.md', finalReport);\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": []
|
|
7
7
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"deepresearch.v1.d.ts","sourceRoot":"","sources":["../../src/lib/deepresearch.v1.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,sBAAsB,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;
|
|
1
|
+
{"version":3,"file":"deepresearch.v1.d.ts","sourceRoot":"","sources":["../../src/lib/deepresearch.v1.ts"],"names":[],"mappings":"AAQA,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,sBAAsB;IACrC,aAAa,EAAE,WAAW,EAAE,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,mBAAmB,EAAE,MAAM,CAAC;CAC7B;AAED,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,sBAAsB,CAAC;CAClC;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,aAAa,EAAE,CAAC;CAC7B;AAkMD,MAAM,WAAW,eAAe;IAC9B,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,oBAAoB,CAAC,EAAE,OAAO,CAAC;CAChC;AAOD,wBAAsB,iBAAiB,CACrC,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,aAAa,EACxB,OAAO,GAAE,eAAoB,iBA6C9B;AAED,wBAAsB,YAAY,CAChC,SAAS,EAAE,MAAM,EACjB,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC;IAAE,KAAK,EAAE,aAAa,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC,CAoBrD"}
|
|
@@ -88,10 +88,9 @@ async function planOutline(userQuery) {
|
|
|
88
88
|
`USER QUERY: ${userQuery}`,
|
|
89
89
|
{}
|
|
90
90
|
);
|
|
91
|
-
const result = output;
|
|
92
91
|
return {
|
|
93
|
-
reportTitle:
|
|
94
|
-
paragraphs:
|
|
92
|
+
reportTitle: output.reportTitle,
|
|
93
|
+
paragraphs: output.sections.map(
|
|
95
94
|
(p) => ({
|
|
96
95
|
title: p.title.trim(),
|
|
97
96
|
content: p.content.trim(),
|
|
@@ -154,8 +153,7 @@ async function summarizeParagraph(userQuery, paragraph, searchQuery, snippets) {
|
|
|
154
153
|
],
|
|
155
154
|
{ userQuery }
|
|
156
155
|
);
|
|
157
|
-
|
|
158
|
-
paragraph.research.latestSummary = out.paragraph_latest_state.trim();
|
|
156
|
+
paragraph.research.latestSummary = output.paragraph_latest_state.trim();
|
|
159
157
|
}
|
|
160
158
|
async function runWebSearch(query) {
|
|
161
159
|
const tvly = tavily();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/lib/deepresearch.v1.ts"],
|
|
4
|
-
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { openai } from '@ai-sdk/openai';\nimport { tavily } from '@tavily/core';\nimport { writeFile } from 'node:fs/promises';\nimport { z } from 'zod';\n\nimport { agent, execute, generate, input, user } from '@deepagents/agent';\n\nexport interface SearchEntry {\n title: string;\n url: string;\n content: string;\n query: string;\n}\n\nexport interface ParagraphResearchState {\n searchHistory: SearchEntry[]; // appended chronologically\n latestSummary: string; // evolving synthesized paragraph content\n reflectionIteration: number; // count of reflection loops executed\n}\n\nexport interface ParagraphPlan {\n title: string;\n content: string; // planned description / intent for the paragraph\n research: ParagraphResearchState;\n}\n\nexport interface ResearchState {\n reportTitle: string;\n paragraphs: ParagraphPlan[];\n}\n\nfunction dedupeSearchEntries(entries: SearchEntry[]): SearchEntry[] {\n const seen = new Set<string>();\n const result: SearchEntry[] = [];\n for (const e of entries) {\n const key = `${e.query}::${e.url ?? e.title}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(e);\n }\n }\n return result;\n}\n\nconst OutlineOutputSchema = z.object({\n reportTitle: z.string().min(5),\n sections: z\n .array(\n z.object({\n title: z.string().min(1),\n content: z.string().min(1),\n }),\n )\n .min(1)\n .max(30),\n});\n\nconst outlineAgent = agent({\n name: 'outline-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You are a Deep Research assistant. Given the USER QUERY, plan a structured report outline.',\n 'Return ONLY valid JSON (array of objects) matching the provided schema with paragraph title and content description.',\n 'Do not include code fences, commentary or reasoning, just JSON.',\n ],\n output: OutlineOutputSchema,\n});\n\nconst FirstSearchOutputSchema = z.object({\n search_query: z.string().min(2),\n reasoning: z.string().optional(),\n});\n\nconst firstSearchPlannerAgent = agent({\n name: 'first-search-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: `You are a Deep Research assistant. Given the USER QUERY plus paragraph title and initial content, craft ONE optimal web search query to collect factual, current information. Return only JSON {\"search_query\": string, \"reasoning\": string}.`,\n output: FirstSearchOutputSchema,\n});\n\nconst ReflectionSearchOutputSchema = z.object({\n search_query: z.string().min(2),\n reasoning: z.string().optional(),\n});\n\nconst reflectionSearchPlannerAgent = agent({\n name: 'reflection-search-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You enrich a paragraph through iterative research. Provided JSON includes the USER QUERY, paragraph title, planned content, and the current drafted summary.',\n 'Identify a missing angle, fact, statistic, counterpoint, timeline, cause/effect, or recent development.',\n 'Return ONLY JSON {\"search_query\": string, \"reasoning\": string}. If no enrichment needed, use an empty string for search_query.',\n ],\n output: ReflectionSearchOutputSchema,\n});\n\nconst ParagraphSummaryOutputSchema = z.object({\n paragraph_latest_state: z.string().min(20),\n});\n\nconst paragraphSummaryAgent = agent({\n name: 'paragraph-summarizer',\n model: openai('gpt-4.1-mini'),\n prompt: [\n 'You are producing a polished paragraph for a research report. Input JSON provides: USER QUERY, title, planned content, search_query used, and an array of textual snippets (search_results).',\n 'Integrate facts cohesively, avoid fluff, cite NO sources inline, keep within ~250 words, maintain factual tone.',\n 'Return ONLY JSON {\"paragraph_latest_state\": string}.',\n ],\n output: ParagraphSummaryOutputSchema,\n});\n\nconst finalReportAgent = agent<{ userQuery: string }>({\n name: 'final_report',\n model: openai('gpt-4.1'),\n prompt: (context) => `\n\t\tYou have finalized paragraphs of a research report as JSON array [{title, paragraph_latest_state}].\n Produce a well-structured Markdown report with: top-level title, table of contents, each section with heading, and a concluding synthesis (add Conclusion if missing).\n Do not hallucinate new sections beyond conclusion. Keep formatting clean.\n `,\n});\n\ntype OutlineOutput = z.infer<typeof OutlineOutputSchema>;\n\nasync function planOutline(userQuery: string) {\n const { output } = await generate(\n outlineAgent,\n `USER QUERY: ${userQuery}`,\n {},\n );\n const result = output as OutlineOutput;\n return {\n reportTitle: result.reportTitle,\n paragraphs: result.sections.map(\n (p: { title: string; content: string }) => ({\n title: p.title.trim(),\n content: p.content.trim(),\n research: {\n latestSummary: '',\n reflectionIteration: 0,\n searchHistory: [],\n },\n }),\n ),\n } satisfies ResearchState;\n}\n\ntype FirstSearchOutput = z.infer<typeof FirstSearchOutputSchema>;\n\nasync function planFirstSearch(userQuery: string, paragraph: ParagraphPlan) {\n const { output } = await generate(\n firstSearchPlannerAgent,\n [\n user(\n `USER QUERY: ${userQuery}\\nTitle: ${paragraph.title}\\nContent: ${paragraph.content}`,\n ),\n ],\n { userQuery },\n );\n return output as FirstSearchOutput;\n}\n\ntype ReflectionSearchOutput = z.infer<typeof ReflectionSearchOutputSchema>;\n\nasync function planReflectionSearch(\n userQuery: string,\n paragraph: ParagraphPlan,\n) {\n const { output } = await generate(\n reflectionSearchPlannerAgent,\n `USER QUERY: ${userQuery}\\n${JSON.stringify({\n title: paragraph.title,\n content: paragraph.content,\n paragraph_latest_state: paragraph.research.latestSummary,\n })}`,\n { userQuery },\n );\n return output as ReflectionSearchOutput;\n}\n\nasync function summarizeParagraph(\n userQuery: string,\n paragraph: ParagraphPlan,\n searchQuery: string,\n snippets: string[],\n) {\n const input = {\n user_query: userQuery,\n title: paragraph.title,\n content: paragraph.content,\n search_query: searchQuery,\n search_results: snippets.slice(0, 8),\n };\n type ParagraphSummaryOutput = z.infer<typeof ParagraphSummaryOutputSchema>;\n const { output } = await generate(\n paragraphSummaryAgent,\n [\n user(\n `\n\t\t\t\tUSER QUERY: ${userQuery}\n\t\t\t\tTitle: ${input.title}\n\t\t\t\tContent: ${input.content}\n\t\t\t\tSearch Query: ${input.search_query}\n\t\t\t\tSearch Results: ${input.search_results.join('\\n\\n---\\n\\n')}\n\t\t\t\t`,\n ),\n ],\n { userQuery },\n );\n const out = output as ParagraphSummaryOutput;\n paragraph.research.latestSummary = out.paragraph_latest_state.trim();\n}\n\nasync function runWebSearch(query: string) {\n const tvly = tavily();\n const response = await tvly.search(query);\n return response.results.map(\n (r) =>\n ({\n query,\n url: r.url,\n title: r.title,\n content: r.content,\n }) satisfies SearchEntry,\n );\n}\n\nfunction collectAllSnippets(p: ParagraphPlan): string[] {\n return p.research.searchHistory\n .map((h) => h.content?.trim())\n .filter((s): s is string => !!s);\n}\n\nexport interface ResearchOptions {\n maxReflections?: number; // per paragraph\n stopOnDuplicateQuery?: boolean;\n}\n\nconst defaultResearchOptions: Required<ResearchOptions> = {\n maxReflections: 2,\n stopOnDuplicateQuery: true,\n};\n\nexport async function researchParagraph(\n userQuery: string,\n paragraph: ParagraphPlan,\n options: ResearchOptions = {},\n) {\n const opts = { ...defaultResearchOptions, ...options };\n const firstPlan = await planFirstSearch(userQuery, paragraph);\n console.log(`\\n=== Researching Paragraph: ${paragraph.title} ===`);\n console.log(\n `Search Query: ${firstPlan.search_query} with reasoning: ${firstPlan.reasoning}`,\n );\n const firstQuery = firstPlan.search_query?.trim();\n if (!firstQuery) return;\n const firstResults = await runWebSearch(firstQuery);\n paragraph.research.searchHistory.push(...firstResults);\n paragraph.research.searchHistory = dedupeSearchEntries(\n paragraph.research.searchHistory,\n );\n await summarizeParagraph(\n userQuery,\n paragraph,\n firstQuery,\n collectAllSnippets(paragraph),\n );\n\n // Reflection loop\n while (paragraph.research.reflectionIteration < opts.maxReflections) {\n const reflection = await planReflectionSearch(userQuery, paragraph);\n const rq = reflection.search_query?.trim();\n if (!rq) break; // model decided no more\n const alreadyUsed = paragraph.research.searchHistory.some(\n (h) => h.query.toLowerCase() === rq.toLowerCase(),\n );\n if (alreadyUsed && opts.stopOnDuplicateQuery) break;\n\n const refResults = await runWebSearch(rq);\n paragraph.research.searchHistory.push(...refResults);\n paragraph.research.searchHistory = dedupeSearchEntries(\n paragraph.research.searchHistory,\n );\n paragraph.research.reflectionIteration += 1;\n await summarizeParagraph(\n userQuery,\n paragraph,\n rq,\n collectAllSnippets(paragraph),\n );\n }\n}\n\nexport async function deepresearch(\n userQuery: string,\n options: ResearchOptions = {},\n): Promise<{ state: ResearchState; markdown: string }> {\n const state = await planOutline(userQuery);\n for (let i = 0; i < state.paragraphs.length; i++) {\n await researchParagraph(userQuery, state.paragraphs[i], options);\n }\n const reportData = state.paragraphs.map((p) => ({\n title: p.title,\n paragraph_latest_state: p.research.latestSummary,\n }));\n const result = await execute(\n finalReportAgent,\n [\n user(\n `User Query: ${userQuery}\\nFormatting: use ascii markdown diagrams to illustrate. I am visual learner and I love markdown.\\nContext: ${reportData.join('\\n\\n')}`,\n ),\n ],\n { userQuery },\n );\n const finalReportMd = await result.text;\n return { state, markdown: finalReportMd };\n}\n\nif (import.meta.main) {\n const userQuery = await input(\n 'How to integrates planning modules from whitepaper like LLM Compiler, plan and solve, plan and act and others into building deepresearch agent?',\n );\n const { state, markdown } = await deepresearch(userQuery, {\n maxReflections: 1,\n });\n const outfile = `deepresearch_report.md`;\n await writeFile(outfile, markdown, 'utf8');\n console.dir(state, { depth: null });\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,YAAY;AACrB,SAAS,cAAc;AACvB,SAAS,cAAc;AACvB,SAAS,iBAAiB;AAC1B,SAAS,SAAS;AAElB,SAAS,OAAO,SAAS,UAAU,OAAO,YAAY;AA0BtD,SAAS,oBAAoB,SAAuC;AAClE,QAAM,OAAO,oBAAI,IAAY;AAC7B,QAAM,SAAwB,CAAC;AAC/B,aAAW,KAAK,SAAS;AACvB,UAAM,MAAM,GAAG,EAAE,KAAK,KAAK,EAAE,OAAO,EAAE,KAAK;AAC3C,QAAI,CAAC,KAAK,IAAI,GAAG,GAAG;AAClB,WAAK,IAAI,GAAG;AACZ,aAAO,KAAK,CAAC;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;AAEA,IAAM,sBAAsB,EAAE,OAAO;AAAA,EACnC,aAAa,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC7B,UAAU,EACP;AAAA,IACC,EAAE,OAAO;AAAA,MACP,OAAO,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,MACvB,SAAS,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,IAC3B,CAAC;AAAA,EACH,EACC,IAAI,CAAC,EACL,IAAI,EAAE;AACX,CAAC;AAED,IAAM,eAAe,MAAM;AAAA,EACzB,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAChC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AACV,CAAC;AAED,IAAM,0BAA0B,EAAE,OAAO;AAAA,EACvC,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,WAAW,EAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAED,IAAM,0BAA0B,MAAM;AAAA,EACpC,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAChC,QAAQ;AAAA,EACR,QAAQ;AACV,CAAC;AAED,IAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,cAAc,EAAE,OAAO,EAAE,IAAI,CAAC;AAAA,EAC9B,WAAW,EAAE,OAAO,EAAE,SAAS;AACjC,CAAC;AAED,IAAM,+BAA+B,MAAM;AAAA,EACzC,MAAM;AAAA,EACN,OAAO,KAAK,oBAAoB;AAAA,EAChC,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AACV,CAAC;AAED,IAAM,+BAA+B,EAAE,OAAO;AAAA,EAC5C,wBAAwB,EAAE,OAAO,EAAE,IAAI,EAAE;AAC3C,CAAC;AAED,IAAM,wBAAwB,MAAM;AAAA,EAClC,MAAM;AAAA,EACN,OAAO,OAAO,cAAc;AAAA,EAC5B,QAAQ;AAAA,IACN;AAAA,IACA;AAAA,IACA;AAAA,EACF;AAAA,EACA,QAAQ;AACV,CAAC;AAED,IAAM,mBAAmB,
|
|
4
|
+
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { openai } from '@ai-sdk/openai';\nimport { tavily } from '@tavily/core';\nimport { writeFile } from 'node:fs/promises';\nimport { z } from 'zod';\n\nimport { agent, execute, generate, input, user } from '@deepagents/agent';\n\nexport interface SearchEntry {\n title: string;\n url: string;\n content: string;\n query: string;\n}\n\nexport interface ParagraphResearchState {\n searchHistory: SearchEntry[]; // appended chronologically\n latestSummary: string; // evolving synthesized paragraph content\n reflectionIteration: number; // count of reflection loops executed\n}\n\nexport interface ParagraphPlan {\n title: string;\n content: string; // planned description / intent for the paragraph\n research: ParagraphResearchState;\n}\n\nexport interface ResearchState {\n reportTitle: string;\n paragraphs: ParagraphPlan[];\n}\n\nfunction dedupeSearchEntries(entries: SearchEntry[]): SearchEntry[] {\n const seen = new Set<string>();\n const result: SearchEntry[] = [];\n for (const e of entries) {\n const key = `${e.query}::${e.url ?? e.title}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(e);\n }\n }\n return result;\n}\n\nconst OutlineOutputSchema = z.object({\n reportTitle: z.string().min(5),\n sections: z\n .array(\n z.object({\n title: z.string().min(1),\n content: z.string().min(1),\n }),\n )\n .min(1)\n .max(30),\n});\n\nconst outlineAgent = agent({\n name: 'outline-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You are a Deep Research assistant. Given the USER QUERY, plan a structured report outline.',\n 'Return ONLY valid JSON (array of objects) matching the provided schema with paragraph title and content description.',\n 'Do not include code fences, commentary or reasoning, just JSON.',\n ],\n output: OutlineOutputSchema,\n});\n\nconst FirstSearchOutputSchema = z.object({\n search_query: z.string().min(2),\n reasoning: z.string().optional(),\n});\n\nconst firstSearchPlannerAgent = agent({\n name: 'first-search-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: `You are a Deep Research assistant. Given the USER QUERY plus paragraph title and initial content, craft ONE optimal web search query to collect factual, current information. Return only JSON {\"search_query\": string, \"reasoning\": string}.`,\n output: FirstSearchOutputSchema,\n});\n\nconst ReflectionSearchOutputSchema = z.object({\n search_query: z.string().min(2),\n reasoning: z.string().optional(),\n});\n\nconst reflectionSearchPlannerAgent = agent({\n name: 'reflection-search-planner',\n model: groq('openai/gpt-oss-20b'),\n prompt: [\n 'You enrich a paragraph through iterative research. Provided JSON includes the USER QUERY, paragraph title, planned content, and the current drafted summary.',\n 'Identify a missing angle, fact, statistic, counterpoint, timeline, cause/effect, or recent development.',\n 'Return ONLY JSON {\"search_query\": string, \"reasoning\": string}. If no enrichment needed, use an empty string for search_query.',\n ],\n output: ReflectionSearchOutputSchema,\n});\n\nconst ParagraphSummaryOutputSchema = z.object({\n paragraph_latest_state: z.string().min(20),\n});\n\nconst paragraphSummaryAgent = agent({\n name: 'paragraph-summarizer',\n model: openai('gpt-4.1-mini'),\n prompt: [\n 'You are producing a polished paragraph for a research report. Input JSON provides: USER QUERY, title, planned content, search_query used, and an array of textual snippets (search_results).',\n 'Integrate facts cohesively, avoid fluff, cite NO sources inline, keep within ~250 words, maintain factual tone.',\n 'Return ONLY JSON {\"paragraph_latest_state\": string}.',\n ],\n output: ParagraphSummaryOutputSchema,\n});\n\nconst finalReportAgent = agent<unknown, { userQuery: string }>({\n name: 'final_report',\n model: openai('gpt-4.1'),\n prompt: (context) => `\n\t\tYou have finalized paragraphs of a research report as JSON array [{title, paragraph_latest_state}].\n Produce a well-structured Markdown report with: top-level title, table of contents, each section with heading, and a concluding synthesis (add Conclusion if missing).\n Do not hallucinate new sections beyond conclusion. Keep formatting clean.\n `,\n});\n\nasync function planOutline(userQuery: string) {\n const { output } = await generate(\n outlineAgent,\n `USER QUERY: ${userQuery}`,\n {},\n );\n return {\n reportTitle: output.reportTitle,\n paragraphs: output.sections.map(\n (p: { title: string; content: string }) => ({\n title: p.title.trim(),\n content: p.content.trim(),\n research: {\n latestSummary: '',\n reflectionIteration: 0,\n searchHistory: [],\n },\n }),\n ),\n } satisfies ResearchState;\n}\n\nasync function planFirstSearch(userQuery: string, paragraph: ParagraphPlan) {\n const { output } = await generate(\n firstSearchPlannerAgent,\n [\n user(\n `USER QUERY: ${userQuery}\\nTitle: ${paragraph.title}\\nContent: ${paragraph.content}`,\n ),\n ],\n { userQuery },\n );\n return output;\n}\n\nasync function planReflectionSearch(\n userQuery: string,\n paragraph: ParagraphPlan,\n) {\n const { output } = await generate(\n reflectionSearchPlannerAgent,\n `USER QUERY: ${userQuery}\\n${JSON.stringify({\n title: paragraph.title,\n content: paragraph.content,\n paragraph_latest_state: paragraph.research.latestSummary,\n })}`,\n { userQuery },\n );\n return output;\n}\n\nasync function summarizeParagraph(\n userQuery: string,\n paragraph: ParagraphPlan,\n searchQuery: string,\n snippets: string[],\n) {\n const input = {\n user_query: userQuery,\n title: paragraph.title,\n content: paragraph.content,\n search_query: searchQuery,\n search_results: snippets.slice(0, 8),\n };\n const { output } = await generate(\n paragraphSummaryAgent,\n [\n user(\n `\n\t\t\t\tUSER QUERY: ${userQuery}\n\t\t\t\tTitle: ${input.title}\n\t\t\t\tContent: ${input.content}\n\t\t\t\tSearch Query: ${input.search_query}\n\t\t\t\tSearch Results: ${input.search_results.join('\\n\\n---\\n\\n')}\n\t\t\t\t`,\n ),\n ],\n { userQuery },\n );\n paragraph.research.latestSummary = output.paragraph_latest_state.trim();\n}\n\nasync function runWebSearch(query: string) {\n const tvly = tavily();\n const response = await tvly.search(query);\n return response.results.map(\n (r) =>\n ({\n query,\n url: r.url,\n title: r.title,\n content: r.content,\n }) satisfies SearchEntry,\n );\n}\n\nfunction collectAllSnippets(p: ParagraphPlan): string[] {\n return p.research.searchHistory\n .map((h) => h.content?.trim())\n .filter((s): s is string => !!s);\n}\n\nexport interface ResearchOptions {\n maxReflections?: number; // per paragraph\n stopOnDuplicateQuery?: boolean;\n}\n\nconst defaultResearchOptions: Required<ResearchOptions> = {\n maxReflections: 2,\n stopOnDuplicateQuery: true,\n};\n\nexport async function researchParagraph(\n userQuery: string,\n paragraph: ParagraphPlan,\n options: ResearchOptions = {},\n) {\n const opts = { ...defaultResearchOptions, ...options };\n const firstPlan = await planFirstSearch(userQuery, paragraph);\n console.log(`\\n=== Researching Paragraph: ${paragraph.title} ===`);\n console.log(\n `Search Query: ${firstPlan.search_query} with reasoning: ${firstPlan.reasoning}`,\n );\n const firstQuery = firstPlan.search_query?.trim();\n if (!firstQuery) return;\n const firstResults = await runWebSearch(firstQuery);\n paragraph.research.searchHistory.push(...firstResults);\n paragraph.research.searchHistory = dedupeSearchEntries(\n paragraph.research.searchHistory,\n );\n await summarizeParagraph(\n userQuery,\n paragraph,\n firstQuery,\n collectAllSnippets(paragraph),\n );\n\n // Reflection loop\n while (paragraph.research.reflectionIteration < opts.maxReflections) {\n const reflection = await planReflectionSearch(userQuery, paragraph);\n const rq = reflection.search_query?.trim();\n if (!rq) break; // model decided no more\n const alreadyUsed = paragraph.research.searchHistory.some(\n (h) => h.query.toLowerCase() === rq.toLowerCase(),\n );\n if (alreadyUsed && opts.stopOnDuplicateQuery) break;\n\n const refResults = await runWebSearch(rq);\n paragraph.research.searchHistory.push(...refResults);\n paragraph.research.searchHistory = dedupeSearchEntries(\n paragraph.research.searchHistory,\n );\n paragraph.research.reflectionIteration += 1;\n await summarizeParagraph(\n userQuery,\n paragraph,\n rq,\n collectAllSnippets(paragraph),\n );\n }\n}\n\nexport async function deepresearch(\n userQuery: string,\n options: ResearchOptions = {},\n): Promise<{ state: ResearchState; markdown: string }> {\n const state = await planOutline(userQuery);\n for (let i = 0; i < state.paragraphs.length; i++) {\n await researchParagraph(userQuery, state.paragraphs[i], options);\n }\n const reportData = state.paragraphs.map((p) => ({\n title: p.title,\n paragraph_latest_state: p.research.latestSummary,\n }));\n const result = await execute(\n finalReportAgent,\n [\n user(\n `User Query: ${userQuery}\\nFormatting: use ascii markdown diagrams to illustrate. I am visual learner and I love markdown.\\nContext: ${reportData.join('\\n\\n')}`,\n ),\n ],\n { userQuery },\n );\n const finalReportMd = await result.text;\n return { state, markdown: finalReportMd };\n}\n\nif (import.meta.main) {\n const userQuery = await input(\n 'How to integrates planning modules from whitepaper like LLM Compiler, plan and solve, plan and act and others into building deepresearch agent?',\n );\n const { state, markdown } = await deepresearch(userQuery, {\n maxReflections: 1,\n });\n const outfile = `deepresearch_report.md`;\n await writeFile(outfile, markdown, 'utf8');\n console.dir(state, { depth: null });\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["input"]
|
|
7
7
|
}
|
|
@@ -92,8 +92,10 @@ var outlineAgent = agent({
|
|
|
92
92
|
inputSchema: z.object({
|
|
93
93
|
outline: OutlineSchema
|
|
94
94
|
})
|
|
95
|
-
// execute: (
|
|
96
|
-
//
|
|
95
|
+
// execute: (
|
|
96
|
+
// { outline },
|
|
97
|
+
// { context }: ToolExecutionOptions<OutlineAgentContext>,
|
|
98
|
+
// ) => {
|
|
97
99
|
// // Store the outline in a file or database
|
|
98
100
|
// console.log('Generated Outline:\n', outline);
|
|
99
101
|
// context.outline = outline;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/deepwiki/complete-wiki.ts", "../../../src/lib/deepwiki/outline-agent.ts"],
|
|
4
|
-
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { defaultSettingsMiddleware, wrapLanguageModel } from 'ai';\nimport { snakeCase } from 'lodash-es';\nimport { writeFile } from 'node:fs/promises';\n\nimport {\n agent,\n execute,\n instructions,\n lmstudio,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, search_content_tool } from '@deepagents/toolbox';\n\nimport { type Outline, buildToc } from './outline-agent.ts';\n\ntype SectionAgentContext = {\n repo_path: string;\n scratchpad: string;\n tree: string;\n toc: string[];\n};\n\n// Agent for writing leaf sections\nconst sectionWriterAgent = agent<SectionAgentContext>({\n name: 'Section Writer',\n model: wrapLanguageModel({\n // model: groq('moonshotai/kimi-k2-instruct-0905'),\n model: lmstudio('openai/gpt-oss-20b'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.5 },\n }),\n }),\n tools: {\n read_file: read_file_tool,\n search_content: search_content_tool,\n },\n prompt: '',\n});\n\n// Agent for writing parent TOC pages\nconst tocPageAgent = agent<SectionAgentContext>({\n name: 'TOC Page Writer',\n model: wrapLanguageModel({\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.1 },\n }),\n }),\n prompt: instructions({\n purpose: [\n 'You create table-of-contents style pages for wiki parent sections.',\n 'Your pages introduce the parent topic and provide an organized overview of child sections.',\n ],\n routine: [\n 'Write a clear, engaging introduction to the parent section topic.',\n 'Provide context about what readers will learn in the child sections.',\n 'Create a structured overview that explains how child sections relate to each other.',\n 'Your content should help readers understand the big picture before diving into specifics.',\n 'Do NOT duplicate detailed content - that belongs in the child pages.',\n ],\n }),\n});\n\ntype WikiResult = {\n files: Record<string, string>; // section title -> file path\n index: string; // main index content\n};\n\n/**\n * Build file path for a section based on its hierarchical path\n * Example: ['Project Overview', 'Architecture'] -> 'docs/project_overview_architecture.md'\n */\nfunction buildFilePath(pathSegments: string[]): string {\n return `${snakeCase(pathSegments.join('_'))}.md`;\n}\n\n/**\n * Write content for a leaf section using the section writer agent\n */\nasync function writeSection(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing section: ${pathSegments.join(' > ')}`);\n\n const result = await execute(\n sectionWriterAgent,\n [\n user(\n `You are writing the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Use the provided tools to inspect relevant files in the repository\n2. Write clear, comprehensive, and accurate markdown content for this section\n3. Include code examples where appropriate\n4. Ensure the content is self-contained and valuable\n5. Focus specifically on the topic: ${item.title}\n\nWrite the section content now.\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Write a TOC-style page for a parent section\n */\nasync function writeTocPage(\n item: Outline[number],\n pathSegments: string[],\n childFiles: Array<{ title: string; path: string }>,\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing TOC page: ${pathSegments.join(' > ')}`);\n\n const childSummaries = childFiles\n .map((child, index) => `${index + 1}. **${child.title}**`)\n .join('\\n');\n\n const childLinks = childFiles\n .map((child) => `- [${child.title}](${child.path})`)\n .join('\\n');\n\n const result = await execute(\n tocPageAgent,\n [\n user(\n `You are creating a table-of-contents page for the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThis parent section has the following child sections:\n${childSummaries}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Write a clear introduction to the \"${item.title}\" topic\n2. Explain what readers will learn from the child sections below\n3. Provide context about how these child sections relate to each other\n4. Keep it concise - this is a navigation page, not the full content\n\nAfter your introduction, you MUST include this exact navigation section:\n\n## Sections\n\n${childLinks}\n\nWrite the TOC page content now (introduction followed by the navigation section above).\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Recursively process outline items and generate markdown files\n */\nasync function processOutlineItem(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n files: Record<string, string>,\n): Promise<void> {\n const currentPath = [...pathSegments, item.title];\n const filePath = buildFilePath(currentPath);\n\n if (!item.sections || item.sections.length === 0) {\n // Leaf node - write comprehensive content\n const content = await writeSection(item, currentPath, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created: ${filePath}`);\n } else {\n // Parent node - process children first, then create TOC page\n const childFiles: Array<{ title: string; path: string }> = [];\n\n for (const child of item.sections) {\n await processOutlineItem(child, currentPath, state, files);\n const childPath = buildFilePath([...currentPath, child.title]);\n childFiles.push({ title: child.title, path: childPath });\n }\n\n // Create TOC page for parent\n const content = await writeTocPage(item, currentPath, childFiles, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created TOC: ${filePath}`);\n }\n}\n\n/**\n * Generate a complete multi-page wiki from an outline\n *\n * This function creates separate markdown files for each section:\n * - Leaf sections get comprehensive content written by agents\n * - Parent sections get TOC-style pages with introductions and links to children\n * - All files use flat naming with full hierarchical path\n */\nexport async function completeWiki(state: {\n repo_path: string;\n outline: Outline;\n tree: string;\n}): Promise<WikiResult> {\n const toc = buildToc(state.outline);\n const files: Record<string, string> = {};\n\n const agentContext: SectionAgentContext = {\n repo_path: state.repo_path,\n scratchpad: '## Scratchpad\\n\\n',\n tree: state.tree,\n toc,\n };\n\n console.log('Starting multi-page wiki generation...');\n\n // Process each top-level item\n for (const item of state.outline) {\n await processOutlineItem(item, [], agentContext, files);\n }\n\n // Create main index page\n const indexLinks = state.outline\n .map((item) => {\n const filePath = buildFilePath([item.title]);\n return `- [${item.title}](${filePath})`;\n })\n .join('\\n');\n\n const index = `# Wiki Index\n\nWelcome to the documentation. This wiki is organized into the following sections:\n\n${indexLinks}\n`;\n\n console.log(`\u2713 Complete! Generated ${Object.keys(files).length} pages`);\n\n return { files, index };\n}\n", "import { groq } from '@ai-sdk/groq';\nimport { type UIMessage, generateId, toUIMessageStream, tool } from 'ai';\nimport z from 'zod';\n\nimport {\n agent,\n execute,\n generate,\n instructions,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, scratchpad_tool } from '@deepagents/toolbox';\n\nconst BaseOutlineItem = z.object({\n title: z.string().trim().min(1, 'Title is required'),\n});\ntype OutlineItem = z.output<typeof BaseOutlineItem> & {\n sections?: z.output<typeof OutlineItemSchema>[];\n};\nconst OutlineItemSchema: z.ZodType<OutlineItem> = z.lazy(() =>\n BaseOutlineItem.extend({\n sections: z.array(OutlineItemSchema).optional(),\n }),\n);\nconst OutlineSchema = z.array(OutlineItemSchema);\nexport type Outline = z.output<typeof OutlineSchema>;\nexport type OutlineAgentContext = {\n repo_path: string;\n outline: z.output<typeof OutlineSchema>;\n scratchpad: string;\n tree: string;\n};\n\nexport const outlineAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n // model: lmstudio('qwen/qwen3-8b'),\n // model: lmstudio('openai/gpt-oss-20b'),\n\n // temperature: 0.1,\n prompt: (context) =>\n instructions({\n purpose: [\n \"You are wiki architect, meticulously analyzing a repository's structure and content to automatically generate a comprehensive, intelligent, and perfectly structured outline, laying the bedrock for exceptional documentation.\",\n '\\n',\n '<RepositoryTree>',\n context?.tree || '',\n '</RepositoryTree>',\n ],\n routine: [],\n // routine: [\n // 'Your primary tool for memory is your `scratchpad`. After every action, you MUST summarize your findings and add them to the scratchpad using the `update_scratchpad` tool.',\n // 'Systematically investigate key files and directories use `search_files`. For each finding add it as a new note to your scratchpad.',\n // 'When you read a file like `README.md` or `package.json`, do not keep the whole content in your head. Instead, summarize the important parts (like headings, dependencies, or scripts) and add that summary to your scratchpad.',\n // 'Continue this process of exploring, summarizing, and adding to your scratchpad until you are confident you have a full picture of the repository.',\n // 'Once you believe you have gathered enough information, your second-to-last step is to review your entire scratchpad to synthesize a plan for the final outline.',\n // 'Finally, based *only* on the information you have gathered in your scratchpad, generate the complete, detailed outline and store it using the `store_outline` tool. You must only call `store_outline` ONCE at the very end.',\n // ],\n }),\n tools: {\n read_file: read_file_tool,\n // read_dir: read_dir_tool,\n // search_files: search_files_tool,\n // file_exists: file_exists_tool,\n update_scratchpad: scratchpad_tool,\n store_outline: tool({\n description: `Use this tool to store the generated outline.\n\t\tThe outline should be a detailed hierarchical structure representing the sections and subsections of the repository documentation. In thory you can nest sections as deep as you want, but try to keep it to 4 levels deep maximum.\n\n\t\t## Example outline\n\t\t[\n\t\t\t{\n\t\t\t\t\"title\": \"xxxx\",\n\t\t\t\t\"sections\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"yyyy\",\n\t\t\t\t\t\tsections: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"title\": \"vvvv\",\n\t\t\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"gggg\",\n\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t]\n\t\t\t`,\n inputSchema: z.object({\n outline: OutlineSchema,\n }),\n // execute: ({ outline }, options) => {\n // const context = toState<OutlineAgentContext>(options);\n // // Store the outline in a file or database\n // console.log('Generated Outline:\\n', outline);\n // context.outline = outline;\n // return 'Outline stored successfully.';\n // },\n }),\n },\n});\n\nexport const outlineCondensedAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Condensed Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n prompt: instructions({\n purpose: [\n 'To intelligently condense and optimize an existing outline by merging redundant sections, removing overly granular subdivisions, and creating a more streamlined, maintainable documentation structure.',\n 'Your goal is to reduce complexity while preserving all essential information and maintaining logical hierarchy.',\n ],\n routine: [\n 'Examine the current outline structure stored in the context. Use your scratchpad to track your analysis.',\n 'Identify sections that are too granular (e.g., sections with only 1-2 subsections that could be merged with their parent).',\n 'Look for redundant or overlapping sections that cover similar topics and can be consolidated.',\n 'Note sections with excessive nesting depth (more than 3-4 levels) that could be flattened.',\n 'Identify sections with very similar titles that could be merged (e.g., \"API Overview\" and \"API Introduction\").',\n 'For each potential consolidation, add a note to your scratchpad explaining the rationale.',\n 'Create a condensed version of the outline that:',\n ' - Merges related subsections into broader topics',\n ' - Reduces nesting depth where appropriate',\n ' - Eliminates redundancy while keeping all unique content areas',\n ' - Maintains a maximum depth of 3 levels unless absolutely necessary',\n ' - Ensures each section has substantial content to document',\n 'Return the condensed outline as structured output.',\n ],\n }),\n output: OutlineSchema,\n});\n\nexport async function generateOutline(state: OutlineAgentContext) {\n const messages: UIMessage[] = [\n user(\n 'Walk through the repository and generate a detailed outline. Make sure to avoid looking into framework generated files and folders. when outline is complete, call the store_outline tool.',\n ),\n ];\n const max_iterations = 3;\n let current_iteration = 0;\n while (current_iteration < max_iterations) {\n console.log(`\\n=== Outline Iteration ${current_iteration + 1} ===\\n`);\n const result = await execute(outlineAgent, messages, state);\n await Array.fromAsync(\n toUIMessageStream({\n stream: result.stream,\n tools: outlineAgent.toToolset(),\n generateMessageId: generateId,\n originalMessages: messages,\n onEnd: async ({ responseMessage }: { responseMessage: UIMessage }) => {\n messages.push(responseMessage);\n },\n }),\n );\n await result.consumeStream();\n const calls = await result.toolCalls;\n const outlineCall = calls.find(\n (t: { toolName: string }) => t.toolName === 'store_outline',\n );\n if (outlineCall) {\n console.log('\\n=== Outline Generation Complete ===\\n');\n state.outline = outlineCall.input.outline;\n break;\n }\n current_iteration++;\n }\n if (!state.outline.length) {\n throw new Error('Outline generation failed.');\n }\n return generate(\n outlineCondensedAgent,\n `Condense and optimize the following outline:\\n\\n${buildToc(state.outline)}`,\n state,\n ).then(({ output }) => output);\n}\n\nfunction slugify(text: string) {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-');\n}\n\nexport function buildToc(\n items: OutlineItem[],\n baseDepth = 1,\n prefix: string[] = [],\n) {\n const lines: string[] = [];\n for (const it of items) {\n const path = [...prefix, it.title];\n const indent = ' '.repeat(Math.max(0, path.length - 1));\n const anchor = slugify(it.title);\n lines.push(`${indent}- [${it.title}](#${anchor})`);\n if (it.sections?.length) {\n lines.push(...buildToc(it.sections, baseDepth + 1, path));\n }\n }\n return lines;\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,QAAAA,aAAY;AACrB,SAAS,2BAA2B,yBAAyB;AAC7D,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAE1B;AAAA,EACE,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA,QAAAC;AAAA,OACK;AACP,SAAS,kBAAAC,iBAAgB,2BAA2B;;;ACZpD,SAAS,YAAY;AACrB,SAAyB,YAAY,mBAAmB,YAAY;AACpE,OAAO,OAAO;AAEd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB,uBAAuB;AAEhD,IAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,mBAAmB;AACrD,CAAC;AAID,IAAM,oBAA4C,EAAE;AAAA,EAAK,MACvD,gBAAgB,OAAO;AAAA,IACrB,UAAU,EAAE,MAAM,iBAAiB,EAAE,SAAS;AAAA,EAChD,CAAC;AACH;AACA,IAAM,gBAAgB,EAAE,MAAM,iBAAiB;AASxC,IAAM,eAAe,MAAoC;AAAA,EAC9D,MAAM;AAAA,EACN,OAAO,KAAK,kCAAkC;AAAA;AAAA;AAAA;AAAA,EAK9C,QAAQ,CAAC,YACP,aAAa;AAAA,IACX,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASZ,CAAC;AAAA,EACH,OAAO;AAAA,IACL,WAAW;AAAA;AAAA;AAAA;AAAA,IAIX,mBAAmB;AAAA,IACnB,eAAe,KAAK;AAAA,MAClB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBb,aAAa,EAAE,OAAO;AAAA,QACpB,SAAS;AAAA,MACX,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { groq } from '@ai-sdk/groq';\nimport { defaultSettingsMiddleware, wrapLanguageModel } from 'ai';\nimport { snakeCase } from 'lodash-es';\nimport { writeFile } from 'node:fs/promises';\n\nimport {\n agent,\n execute,\n instructions,\n lmstudio,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, search_content_tool } from '@deepagents/toolbox';\n\nimport { type Outline, buildToc } from './outline-agent.ts';\n\ntype SectionAgentContext = {\n repo_path: string;\n scratchpad: string;\n tree: string;\n toc: string[];\n};\n\n// Agent for writing leaf sections\nconst sectionWriterAgent = agent<unknown, SectionAgentContext>({\n name: 'Section Writer',\n model: wrapLanguageModel({\n // model: groq('moonshotai/kimi-k2-instruct-0905'),\n model: lmstudio('openai/gpt-oss-20b'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.5 },\n }),\n }),\n tools: {\n read_file: read_file_tool,\n search_content: search_content_tool,\n },\n prompt: '',\n});\n\n// Agent for writing parent TOC pages\nconst tocPageAgent = agent<unknown, SectionAgentContext>({\n name: 'TOC Page Writer',\n model: wrapLanguageModel({\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.1 },\n }),\n }),\n prompt: instructions({\n purpose: [\n 'You create table-of-contents style pages for wiki parent sections.',\n 'Your pages introduce the parent topic and provide an organized overview of child sections.',\n ],\n routine: [\n 'Write a clear, engaging introduction to the parent section topic.',\n 'Provide context about what readers will learn in the child sections.',\n 'Create a structured overview that explains how child sections relate to each other.',\n 'Your content should help readers understand the big picture before diving into specifics.',\n 'Do NOT duplicate detailed content - that belongs in the child pages.',\n ],\n }),\n});\n\ntype WikiResult = {\n files: Record<string, string>; // section title -> file path\n index: string; // main index content\n};\n\n/**\n * Build file path for a section based on its hierarchical path\n * Example: ['Project Overview', 'Architecture'] -> 'docs/project_overview_architecture.md'\n */\nfunction buildFilePath(pathSegments: string[]): string {\n return `${snakeCase(pathSegments.join('_'))}.md`;\n}\n\n/**\n * Write content for a leaf section using the section writer agent\n */\nasync function writeSection(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing section: ${pathSegments.join(' > ')}`);\n\n const result = await execute(\n sectionWriterAgent,\n [\n user(\n `You are writing the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Use the provided tools to inspect relevant files in the repository\n2. Write clear, comprehensive, and accurate markdown content for this section\n3. Include code examples where appropriate\n4. Ensure the content is self-contained and valuable\n5. Focus specifically on the topic: ${item.title}\n\nWrite the section content now.\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Write a TOC-style page for a parent section\n */\nasync function writeTocPage(\n item: Outline[number],\n pathSegments: string[],\n childFiles: Array<{ title: string; path: string }>,\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing TOC page: ${pathSegments.join(' > ')}`);\n\n const childSummaries = childFiles\n .map((child, index) => `${index + 1}. **${child.title}**`)\n .join('\\n');\n\n const childLinks = childFiles\n .map((child) => `- [${child.title}](${child.path})`)\n .join('\\n');\n\n const result = await execute(\n tocPageAgent,\n [\n user(\n `You are creating a table-of-contents page for the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThis parent section has the following child sections:\n${childSummaries}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Write a clear introduction to the \"${item.title}\" topic\n2. Explain what readers will learn from the child sections below\n3. Provide context about how these child sections relate to each other\n4. Keep it concise - this is a navigation page, not the full content\n\nAfter your introduction, you MUST include this exact navigation section:\n\n## Sections\n\n${childLinks}\n\nWrite the TOC page content now (introduction followed by the navigation section above).\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Recursively process outline items and generate markdown files\n */\nasync function processOutlineItem(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n files: Record<string, string>,\n): Promise<void> {\n const currentPath = [...pathSegments, item.title];\n const filePath = buildFilePath(currentPath);\n\n if (!item.sections || item.sections.length === 0) {\n // Leaf node - write comprehensive content\n const content = await writeSection(item, currentPath, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created: ${filePath}`);\n } else {\n // Parent node - process children first, then create TOC page\n const childFiles: Array<{ title: string; path: string }> = [];\n\n for (const child of item.sections) {\n await processOutlineItem(child, currentPath, state, files);\n const childPath = buildFilePath([...currentPath, child.title]);\n childFiles.push({ title: child.title, path: childPath });\n }\n\n // Create TOC page for parent\n const content = await writeTocPage(item, currentPath, childFiles, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created TOC: ${filePath}`);\n }\n}\n\n/**\n * Generate a complete multi-page wiki from an outline\n *\n * This function creates separate markdown files for each section:\n * - Leaf sections get comprehensive content written by agents\n * - Parent sections get TOC-style pages with introductions and links to children\n * - All files use flat naming with full hierarchical path\n */\nexport async function completeWiki(state: {\n repo_path: string;\n outline: Outline;\n tree: string;\n}): Promise<WikiResult> {\n const toc = buildToc(state.outline);\n const files: Record<string, string> = {};\n\n const agentContext: SectionAgentContext = {\n repo_path: state.repo_path,\n scratchpad: '## Scratchpad\\n\\n',\n tree: state.tree,\n toc,\n };\n\n console.log('Starting multi-page wiki generation...');\n\n // Process each top-level item\n for (const item of state.outline) {\n await processOutlineItem(item, [], agentContext, files);\n }\n\n // Create main index page\n const indexLinks = state.outline\n .map((item) => {\n const filePath = buildFilePath([item.title]);\n return `- [${item.title}](${filePath})`;\n })\n .join('\\n');\n\n const index = `# Wiki Index\n\nWelcome to the documentation. This wiki is organized into the following sections:\n\n${indexLinks}\n`;\n\n console.log(`\u2713 Complete! Generated ${Object.keys(files).length} pages`);\n\n return { files, index };\n}\n", "import { groq } from '@ai-sdk/groq';\nimport { type UIMessage, generateId, toUIMessageStream, tool } from 'ai';\nimport z from 'zod';\n\nimport {\n agent,\n execute,\n generate,\n instructions,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, scratchpad_tool } from '@deepagents/toolbox';\n\nconst BaseOutlineItem = z.object({\n title: z.string().trim().min(1, 'Title is required'),\n});\ntype OutlineItem = z.output<typeof BaseOutlineItem> & {\n sections?: z.output<typeof OutlineItemSchema>[];\n};\nconst OutlineItemSchema: z.ZodType<OutlineItem> = z.lazy(() =>\n BaseOutlineItem.extend({\n sections: z.array(OutlineItemSchema).optional(),\n }),\n);\nconst OutlineSchema = z.array(OutlineItemSchema);\nexport type Outline = z.output<typeof OutlineSchema>;\nexport type OutlineAgentContext = {\n repo_path: string;\n outline: z.output<typeof OutlineSchema>;\n scratchpad: string;\n tree: string;\n};\n\nexport const outlineAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n // model: lmstudio('qwen/qwen3-8b'),\n // model: lmstudio('openai/gpt-oss-20b'),\n\n // temperature: 0.1,\n prompt: (context) =>\n instructions({\n purpose: [\n \"You are wiki architect, meticulously analyzing a repository's structure and content to automatically generate a comprehensive, intelligent, and perfectly structured outline, laying the bedrock for exceptional documentation.\",\n '\\n',\n '<RepositoryTree>',\n context?.tree || '',\n '</RepositoryTree>',\n ],\n routine: [],\n // routine: [\n // 'Your primary tool for memory is your `scratchpad`. After every action, you MUST summarize your findings and add them to the scratchpad using the `update_scratchpad` tool.',\n // 'Systematically investigate key files and directories use `search_files`. For each finding add it as a new note to your scratchpad.',\n // 'When you read a file like `README.md` or `package.json`, do not keep the whole content in your head. Instead, summarize the important parts (like headings, dependencies, or scripts) and add that summary to your scratchpad.',\n // 'Continue this process of exploring, summarizing, and adding to your scratchpad until you are confident you have a full picture of the repository.',\n // 'Once you believe you have gathered enough information, your second-to-last step is to review your entire scratchpad to synthesize a plan for the final outline.',\n // 'Finally, based *only* on the information you have gathered in your scratchpad, generate the complete, detailed outline and store it using the `store_outline` tool. You must only call `store_outline` ONCE at the very end.',\n // ],\n }),\n tools: {\n read_file: read_file_tool,\n // read_dir: read_dir_tool,\n // search_files: search_files_tool,\n // file_exists: file_exists_tool,\n update_scratchpad: scratchpad_tool,\n store_outline: tool({\n description: `Use this tool to store the generated outline.\n\t\tThe outline should be a detailed hierarchical structure representing the sections and subsections of the repository documentation. In thory you can nest sections as deep as you want, but try to keep it to 4 levels deep maximum.\n\n\t\t## Example outline\n\t\t[\n\t\t\t{\n\t\t\t\t\"title\": \"xxxx\",\n\t\t\t\t\"sections\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"yyyy\",\n\t\t\t\t\t\tsections: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"title\": \"vvvv\",\n\t\t\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"gggg\",\n\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t]\n\t\t\t`,\n inputSchema: z.object({\n outline: OutlineSchema,\n }),\n // execute: (\n // { outline },\n // { context }: ToolExecutionOptions<OutlineAgentContext>,\n // ) => {\n // // Store the outline in a file or database\n // console.log('Generated Outline:\\n', outline);\n // context.outline = outline;\n // return 'Outline stored successfully.';\n // },\n }),\n },\n});\n\nexport const outlineCondensedAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Condensed Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n prompt: instructions({\n purpose: [\n 'To intelligently condense and optimize an existing outline by merging redundant sections, removing overly granular subdivisions, and creating a more streamlined, maintainable documentation structure.',\n 'Your goal is to reduce complexity while preserving all essential information and maintaining logical hierarchy.',\n ],\n routine: [\n 'Examine the current outline structure stored in the context. Use your scratchpad to track your analysis.',\n 'Identify sections that are too granular (e.g., sections with only 1-2 subsections that could be merged with their parent).',\n 'Look for redundant or overlapping sections that cover similar topics and can be consolidated.',\n 'Note sections with excessive nesting depth (more than 3-4 levels) that could be flattened.',\n 'Identify sections with very similar titles that could be merged (e.g., \"API Overview\" and \"API Introduction\").',\n 'For each potential consolidation, add a note to your scratchpad explaining the rationale.',\n 'Create a condensed version of the outline that:',\n ' - Merges related subsections into broader topics',\n ' - Reduces nesting depth where appropriate',\n ' - Eliminates redundancy while keeping all unique content areas',\n ' - Maintains a maximum depth of 3 levels unless absolutely necessary',\n ' - Ensures each section has substantial content to document',\n 'Return the condensed outline as structured output.',\n ],\n }),\n output: OutlineSchema,\n});\n\nexport async function generateOutline(state: OutlineAgentContext) {\n const messages: UIMessage[] = [\n user(\n 'Walk through the repository and generate a detailed outline. Make sure to avoid looking into framework generated files and folders. when outline is complete, call the store_outline tool.',\n ),\n ];\n const max_iterations = 3;\n let current_iteration = 0;\n while (current_iteration < max_iterations) {\n console.log(`\\n=== Outline Iteration ${current_iteration + 1} ===\\n`);\n const result = await execute(outlineAgent, messages, state);\n await Array.fromAsync(\n toUIMessageStream({\n stream: result.stream,\n tools: outlineAgent.toToolset(),\n generateMessageId: generateId,\n originalMessages: messages,\n onEnd: async ({ responseMessage }: { responseMessage: UIMessage }) => {\n messages.push(responseMessage);\n },\n }),\n );\n await result.consumeStream();\n const calls = await result.toolCalls;\n const outlineCall = calls.find(\n (t: { toolName: string }) => t.toolName === 'store_outline',\n );\n if (outlineCall) {\n console.log('\\n=== Outline Generation Complete ===\\n');\n state.outline = outlineCall.input.outline;\n break;\n }\n current_iteration++;\n }\n if (!state.outline.length) {\n throw new Error('Outline generation failed.');\n }\n return generate(\n outlineCondensedAgent,\n `Condense and optimize the following outline:\\n\\n${buildToc(state.outline)}`,\n state,\n ).then(({ output }) => output);\n}\n\nfunction slugify(text: string) {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-');\n}\n\nexport function buildToc(\n items: OutlineItem[],\n baseDepth = 1,\n prefix: string[] = [],\n) {\n const lines: string[] = [];\n for (const it of items) {\n const path = [...prefix, it.title];\n const indent = ' '.repeat(Math.max(0, path.length - 1));\n const anchor = slugify(it.title);\n lines.push(`${indent}- [${it.title}](#${anchor})`);\n if (it.sections?.length) {\n lines.push(...buildToc(it.sections, baseDepth + 1, path));\n }\n }\n return lines;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["groq", "agent", "execute", "instructions", "user", "read_file_tool", "agent", "read_file_tool", "groq", "instructions", "execute", "user"]
|
|
7
7
|
}
|
|
@@ -96,8 +96,10 @@ var outlineAgent = agent({
|
|
|
96
96
|
inputSchema: z.object({
|
|
97
97
|
outline: OutlineSchema
|
|
98
98
|
})
|
|
99
|
-
// execute: (
|
|
100
|
-
//
|
|
99
|
+
// execute: (
|
|
100
|
+
// { outline },
|
|
101
|
+
// { context }: ToolExecutionOptions<OutlineAgentContext>,
|
|
102
|
+
// ) => {
|
|
101
103
|
// // Store the outline in a file or database
|
|
102
104
|
// console.log('Generated Outline:\n', outline);
|
|
103
105
|
// context.outline = outline;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../../src/lib/deepwiki/deepwiki.ts", "../../../src/lib/deepwiki/complete-wiki.ts", "../../../src/lib/deepwiki/outline-agent.ts"],
|
|
4
|
-
"sourcesContent": ["import { writeFile } from 'node:fs/promises';\n\nimport { repoTree } from '@deepagents/toolbox';\n\nimport { completeWiki } from './complete-wiki.ts';\nimport { type OutlineAgentContext } from './outline-agent.ts';\n\nconst state: OutlineAgentContext = {\n repo_path: '/Users/ezzabuzaid/Desktop/mo/cold-ambulance',\n // outline: [JSON.parse(await readFile('./outline.json', 'utf-8'))],\n outline: [\n {\n title: 'Project Overview',\n sections: [\n {\n title: 'Healthcare Platform Architecture',\n sections: [\n {\n title: 'Multi-Tenant Structure',\n },\n {\n title: 'Modular Monorepo Setup',\n },\n ],\n },\n {\n title: 'Technology Stack',\n },\n {\n title: 'Multi-Tenant Design',\n sections: [\n {\n title: 'Customer and Vendor Separation',\n },\n {\n title: 'Shared Resources',\n },\n ],\n },\n {\n title: 'API-First Approach',\n },\n ],\n },\n ],\n scratchpad: '## Scratchpad\\n\\n',\n tree: await repoTree('/Users/ezzabuzaid/Desktop/mo/cold-ambulance'),\n};\n\n// const outline = await generateOutline(state);\n\n// await writeFile(\n// './outline_large.json',\n// JSON.stringify(state.outline, null, 2),\n// 'utf-8',\n// );\n// await writeFile('./outline.json', JSON.stringify(outline, null, 2), 'utf-8');\n\n// const finalDoc = await generateWiki({\n// repo_path: state.repo_path,\n// outline: state.outline,\n// tree: state.tree,\n// });\n// const finalDoc = await singlePageWiki({\n// repo_path: state.repo_path,\n// outline: state.outline,\n// tree: state.tree,\n// });\n// await writeFile('./wiki.md', finalDoc, 'utf-8');\n\nconst result = await completeWiki({\n repo_path: state.repo_path,\n outline: state.outline,\n tree: state.tree,\n});\n\n// Write index\nawait writeFile('docs/index.md', result.index, 'utf-8');\n\n// All section files are already written to docs/\nconsole.log('Generated files:', result.files);\n", "import { groq } from '@ai-sdk/groq';\nimport { defaultSettingsMiddleware, wrapLanguageModel } from 'ai';\nimport { snakeCase } from 'lodash-es';\nimport { writeFile } from 'node:fs/promises';\n\nimport {\n agent,\n execute,\n instructions,\n lmstudio,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, search_content_tool } from '@deepagents/toolbox';\n\nimport { type Outline, buildToc } from './outline-agent.ts';\n\ntype SectionAgentContext = {\n repo_path: string;\n scratchpad: string;\n tree: string;\n toc: string[];\n};\n\n// Agent for writing leaf sections\nconst sectionWriterAgent = agent<SectionAgentContext>({\n name: 'Section Writer',\n model: wrapLanguageModel({\n // model: groq('moonshotai/kimi-k2-instruct-0905'),\n model: lmstudio('openai/gpt-oss-20b'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.5 },\n }),\n }),\n tools: {\n read_file: read_file_tool,\n search_content: search_content_tool,\n },\n prompt: '',\n});\n\n// Agent for writing parent TOC pages\nconst tocPageAgent = agent<SectionAgentContext>({\n name: 'TOC Page Writer',\n model: wrapLanguageModel({\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.1 },\n }),\n }),\n prompt: instructions({\n purpose: [\n 'You create table-of-contents style pages for wiki parent sections.',\n 'Your pages introduce the parent topic and provide an organized overview of child sections.',\n ],\n routine: [\n 'Write a clear, engaging introduction to the parent section topic.',\n 'Provide context about what readers will learn in the child sections.',\n 'Create a structured overview that explains how child sections relate to each other.',\n 'Your content should help readers understand the big picture before diving into specifics.',\n 'Do NOT duplicate detailed content - that belongs in the child pages.',\n ],\n }),\n});\n\ntype WikiResult = {\n files: Record<string, string>; // section title -> file path\n index: string; // main index content\n};\n\n/**\n * Build file path for a section based on its hierarchical path\n * Example: ['Project Overview', 'Architecture'] -> 'docs/project_overview_architecture.md'\n */\nfunction buildFilePath(pathSegments: string[]): string {\n return `${snakeCase(pathSegments.join('_'))}.md`;\n}\n\n/**\n * Write content for a leaf section using the section writer agent\n */\nasync function writeSection(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing section: ${pathSegments.join(' > ')}`);\n\n const result = await execute(\n sectionWriterAgent,\n [\n user(\n `You are writing the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Use the provided tools to inspect relevant files in the repository\n2. Write clear, comprehensive, and accurate markdown content for this section\n3. Include code examples where appropriate\n4. Ensure the content is self-contained and valuable\n5. Focus specifically on the topic: ${item.title}\n\nWrite the section content now.\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Write a TOC-style page for a parent section\n */\nasync function writeTocPage(\n item: Outline[number],\n pathSegments: string[],\n childFiles: Array<{ title: string; path: string }>,\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing TOC page: ${pathSegments.join(' > ')}`);\n\n const childSummaries = childFiles\n .map((child, index) => `${index + 1}. **${child.title}**`)\n .join('\\n');\n\n const childLinks = childFiles\n .map((child) => `- [${child.title}](${child.path})`)\n .join('\\n');\n\n const result = await execute(\n tocPageAgent,\n [\n user(\n `You are creating a table-of-contents page for the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThis parent section has the following child sections:\n${childSummaries}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Write a clear introduction to the \"${item.title}\" topic\n2. Explain what readers will learn from the child sections below\n3. Provide context about how these child sections relate to each other\n4. Keep it concise - this is a navigation page, not the full content\n\nAfter your introduction, you MUST include this exact navigation section:\n\n## Sections\n\n${childLinks}\n\nWrite the TOC page content now (introduction followed by the navigation section above).\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Recursively process outline items and generate markdown files\n */\nasync function processOutlineItem(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n files: Record<string, string>,\n): Promise<void> {\n const currentPath = [...pathSegments, item.title];\n const filePath = buildFilePath(currentPath);\n\n if (!item.sections || item.sections.length === 0) {\n // Leaf node - write comprehensive content\n const content = await writeSection(item, currentPath, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created: ${filePath}`);\n } else {\n // Parent node - process children first, then create TOC page\n const childFiles: Array<{ title: string; path: string }> = [];\n\n for (const child of item.sections) {\n await processOutlineItem(child, currentPath, state, files);\n const childPath = buildFilePath([...currentPath, child.title]);\n childFiles.push({ title: child.title, path: childPath });\n }\n\n // Create TOC page for parent\n const content = await writeTocPage(item, currentPath, childFiles, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created TOC: ${filePath}`);\n }\n}\n\n/**\n * Generate a complete multi-page wiki from an outline\n *\n * This function creates separate markdown files for each section:\n * - Leaf sections get comprehensive content written by agents\n * - Parent sections get TOC-style pages with introductions and links to children\n * - All files use flat naming with full hierarchical path\n */\nexport async function completeWiki(state: {\n repo_path: string;\n outline: Outline;\n tree: string;\n}): Promise<WikiResult> {\n const toc = buildToc(state.outline);\n const files: Record<string, string> = {};\n\n const agentContext: SectionAgentContext = {\n repo_path: state.repo_path,\n scratchpad: '## Scratchpad\\n\\n',\n tree: state.tree,\n toc,\n };\n\n console.log('Starting multi-page wiki generation...');\n\n // Process each top-level item\n for (const item of state.outline) {\n await processOutlineItem(item, [], agentContext, files);\n }\n\n // Create main index page\n const indexLinks = state.outline\n .map((item) => {\n const filePath = buildFilePath([item.title]);\n return `- [${item.title}](${filePath})`;\n })\n .join('\\n');\n\n const index = `# Wiki Index\n\nWelcome to the documentation. This wiki is organized into the following sections:\n\n${indexLinks}\n`;\n\n console.log(`\u2713 Complete! Generated ${Object.keys(files).length} pages`);\n\n return { files, index };\n}\n", "import { groq } from '@ai-sdk/groq';\nimport { type UIMessage, generateId, toUIMessageStream, tool } from 'ai';\nimport z from 'zod';\n\nimport {\n agent,\n execute,\n generate,\n instructions,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, scratchpad_tool } from '@deepagents/toolbox';\n\nconst BaseOutlineItem = z.object({\n title: z.string().trim().min(1, 'Title is required'),\n});\ntype OutlineItem = z.output<typeof BaseOutlineItem> & {\n sections?: z.output<typeof OutlineItemSchema>[];\n};\nconst OutlineItemSchema: z.ZodType<OutlineItem> = z.lazy(() =>\n BaseOutlineItem.extend({\n sections: z.array(OutlineItemSchema).optional(),\n }),\n);\nconst OutlineSchema = z.array(OutlineItemSchema);\nexport type Outline = z.output<typeof OutlineSchema>;\nexport type OutlineAgentContext = {\n repo_path: string;\n outline: z.output<typeof OutlineSchema>;\n scratchpad: string;\n tree: string;\n};\n\nexport const outlineAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n // model: lmstudio('qwen/qwen3-8b'),\n // model: lmstudio('openai/gpt-oss-20b'),\n\n // temperature: 0.1,\n prompt: (context) =>\n instructions({\n purpose: [\n \"You are wiki architect, meticulously analyzing a repository's structure and content to automatically generate a comprehensive, intelligent, and perfectly structured outline, laying the bedrock for exceptional documentation.\",\n '\\n',\n '<RepositoryTree>',\n context?.tree || '',\n '</RepositoryTree>',\n ],\n routine: [],\n // routine: [\n // 'Your primary tool for memory is your `scratchpad`. After every action, you MUST summarize your findings and add them to the scratchpad using the `update_scratchpad` tool.',\n // 'Systematically investigate key files and directories use `search_files`. For each finding add it as a new note to your scratchpad.',\n // 'When you read a file like `README.md` or `package.json`, do not keep the whole content in your head. Instead, summarize the important parts (like headings, dependencies, or scripts) and add that summary to your scratchpad.',\n // 'Continue this process of exploring, summarizing, and adding to your scratchpad until you are confident you have a full picture of the repository.',\n // 'Once you believe you have gathered enough information, your second-to-last step is to review your entire scratchpad to synthesize a plan for the final outline.',\n // 'Finally, based *only* on the information you have gathered in your scratchpad, generate the complete, detailed outline and store it using the `store_outline` tool. You must only call `store_outline` ONCE at the very end.',\n // ],\n }),\n tools: {\n read_file: read_file_tool,\n // read_dir: read_dir_tool,\n // search_files: search_files_tool,\n // file_exists: file_exists_tool,\n update_scratchpad: scratchpad_tool,\n store_outline: tool({\n description: `Use this tool to store the generated outline.\n\t\tThe outline should be a detailed hierarchical structure representing the sections and subsections of the repository documentation. In thory you can nest sections as deep as you want, but try to keep it to 4 levels deep maximum.\n\n\t\t## Example outline\n\t\t[\n\t\t\t{\n\t\t\t\t\"title\": \"xxxx\",\n\t\t\t\t\"sections\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"yyyy\",\n\t\t\t\t\t\tsections: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"title\": \"vvvv\",\n\t\t\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"gggg\",\n\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t]\n\t\t\t`,\n inputSchema: z.object({\n outline: OutlineSchema,\n }),\n // execute: ({ outline }, options) => {\n // const context = toState<OutlineAgentContext>(options);\n // // Store the outline in a file or database\n // console.log('Generated Outline:\\n', outline);\n // context.outline = outline;\n // return 'Outline stored successfully.';\n // },\n }),\n },\n});\n\nexport const outlineCondensedAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Condensed Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n prompt: instructions({\n purpose: [\n 'To intelligently condense and optimize an existing outline by merging redundant sections, removing overly granular subdivisions, and creating a more streamlined, maintainable documentation structure.',\n 'Your goal is to reduce complexity while preserving all essential information and maintaining logical hierarchy.',\n ],\n routine: [\n 'Examine the current outline structure stored in the context. Use your scratchpad to track your analysis.',\n 'Identify sections that are too granular (e.g., sections with only 1-2 subsections that could be merged with their parent).',\n 'Look for redundant or overlapping sections that cover similar topics and can be consolidated.',\n 'Note sections with excessive nesting depth (more than 3-4 levels) that could be flattened.',\n 'Identify sections with very similar titles that could be merged (e.g., \"API Overview\" and \"API Introduction\").',\n 'For each potential consolidation, add a note to your scratchpad explaining the rationale.',\n 'Create a condensed version of the outline that:',\n ' - Merges related subsections into broader topics',\n ' - Reduces nesting depth where appropriate',\n ' - Eliminates redundancy while keeping all unique content areas',\n ' - Maintains a maximum depth of 3 levels unless absolutely necessary',\n ' - Ensures each section has substantial content to document',\n 'Return the condensed outline as structured output.',\n ],\n }),\n output: OutlineSchema,\n});\n\nexport async function generateOutline(state: OutlineAgentContext) {\n const messages: UIMessage[] = [\n user(\n 'Walk through the repository and generate a detailed outline. Make sure to avoid looking into framework generated files and folders. when outline is complete, call the store_outline tool.',\n ),\n ];\n const max_iterations = 3;\n let current_iteration = 0;\n while (current_iteration < max_iterations) {\n console.log(`\\n=== Outline Iteration ${current_iteration + 1} ===\\n`);\n const result = await execute(outlineAgent, messages, state);\n await Array.fromAsync(\n toUIMessageStream({\n stream: result.stream,\n tools: outlineAgent.toToolset(),\n generateMessageId: generateId,\n originalMessages: messages,\n onEnd: async ({ responseMessage }: { responseMessage: UIMessage }) => {\n messages.push(responseMessage);\n },\n }),\n );\n await result.consumeStream();\n const calls = await result.toolCalls;\n const outlineCall = calls.find(\n (t: { toolName: string }) => t.toolName === 'store_outline',\n );\n if (outlineCall) {\n console.log('\\n=== Outline Generation Complete ===\\n');\n state.outline = outlineCall.input.outline;\n break;\n }\n current_iteration++;\n }\n if (!state.outline.length) {\n throw new Error('Outline generation failed.');\n }\n return generate(\n outlineCondensedAgent,\n `Condense and optimize the following outline:\\n\\n${buildToc(state.outline)}`,\n state,\n ).then(({ output }) => output);\n}\n\nfunction slugify(text: string) {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-');\n}\n\nexport function buildToc(\n items: OutlineItem[],\n baseDepth = 1,\n prefix: string[] = [],\n) {\n const lines: string[] = [];\n for (const it of items) {\n const path = [...prefix, it.title];\n const indent = ' '.repeat(Math.max(0, path.length - 1));\n const anchor = slugify(it.title);\n lines.push(`${indent}- [${it.title}](#${anchor})`);\n if (it.sections?.length) {\n lines.push(...buildToc(it.sections, baseDepth + 1, path));\n }\n }\n return lines;\n}\n"],
|
|
5
|
-
"mappings": ";AAAA,SAAS,aAAAA,kBAAiB;AAE1B,SAAS,gBAAgB;;;ACFzB,SAAS,QAAAC,aAAY;AACrB,SAAS,2BAA2B,yBAAyB;AAC7D,SAAS,iBAAiB;AAC1B,SAAS,iBAAiB;AAE1B;AAAA,EACE,SAAAC;AAAA,EACA,WAAAC;AAAA,EACA,gBAAAC;AAAA,EACA;AAAA,EACA,QAAAC;AAAA,OACK;AACP,SAAS,kBAAAC,iBAAgB,2BAA2B;;;ACZpD,SAAS,YAAY;AACrB,SAAyB,YAAY,mBAAmB,YAAY;AACpE,OAAO,OAAO;AAEd;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AACP,SAAS,gBAAgB,uBAAuB;AAEhD,IAAM,kBAAkB,EAAE,OAAO;AAAA,EAC/B,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,GAAG,mBAAmB;AACrD,CAAC;AAID,IAAM,oBAA4C,EAAE;AAAA,EAAK,MACvD,gBAAgB,OAAO;AAAA,IACrB,UAAU,EAAE,MAAM,iBAAiB,EAAE,SAAS;AAAA,EAChD,CAAC;AACH;AACA,IAAM,gBAAgB,EAAE,MAAM,iBAAiB;AASxC,IAAM,eAAe,MAAoC;AAAA,EAC9D,MAAM;AAAA,EACN,OAAO,KAAK,kCAAkC;AAAA;AAAA;AAAA;AAAA,EAK9C,QAAQ,CAAC,YACP,aAAa;AAAA,IACX,SAAS;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,QAAQ;AAAA,MACjB;AAAA,IACF;AAAA,IACA,SAAS,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASZ,CAAC;AAAA,EACH,OAAO;AAAA,IACL,WAAW;AAAA;AAAA;AAAA;AAAA,IAIX,mBAAmB;AAAA,IACnB,eAAe,KAAK;AAAA,MAClB,aAAa;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAyBb,aAAa,EAAE,OAAO;AAAA,QACpB,SAAS;AAAA,MACX,CAAC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,
|
|
4
|
+
"sourcesContent": ["import { writeFile } from 'node:fs/promises';\n\nimport { repoTree } from '@deepagents/toolbox';\n\nimport { completeWiki } from './complete-wiki.ts';\nimport { type OutlineAgentContext } from './outline-agent.ts';\n\nconst state: OutlineAgentContext = {\n repo_path: '/Users/ezzabuzaid/Desktop/mo/cold-ambulance',\n // outline: [JSON.parse(await readFile('./outline.json', 'utf-8'))],\n outline: [\n {\n title: 'Project Overview',\n sections: [\n {\n title: 'Healthcare Platform Architecture',\n sections: [\n {\n title: 'Multi-Tenant Structure',\n },\n {\n title: 'Modular Monorepo Setup',\n },\n ],\n },\n {\n title: 'Technology Stack',\n },\n {\n title: 'Multi-Tenant Design',\n sections: [\n {\n title: 'Customer and Vendor Separation',\n },\n {\n title: 'Shared Resources',\n },\n ],\n },\n {\n title: 'API-First Approach',\n },\n ],\n },\n ],\n scratchpad: '## Scratchpad\\n\\n',\n tree: await repoTree('/Users/ezzabuzaid/Desktop/mo/cold-ambulance'),\n};\n\n// const outline = await generateOutline(state);\n\n// await writeFile(\n// './outline_large.json',\n// JSON.stringify(state.outline, null, 2),\n// 'utf-8',\n// );\n// await writeFile('./outline.json', JSON.stringify(outline, null, 2), 'utf-8');\n\n// const finalDoc = await generateWiki({\n// repo_path: state.repo_path,\n// outline: state.outline,\n// tree: state.tree,\n// });\n// const finalDoc = await singlePageWiki({\n// repo_path: state.repo_path,\n// outline: state.outline,\n// tree: state.tree,\n// });\n// await writeFile('./wiki.md', finalDoc, 'utf-8');\n\nconst result = await completeWiki({\n repo_path: state.repo_path,\n outline: state.outline,\n tree: state.tree,\n});\n\n// Write index\nawait writeFile('docs/index.md', result.index, 'utf-8');\n\n// All section files are already written to docs/\nconsole.log('Generated files:', result.files);\n", "import { groq } from '@ai-sdk/groq';\nimport { defaultSettingsMiddleware, wrapLanguageModel } from 'ai';\nimport { snakeCase } from 'lodash-es';\nimport { writeFile } from 'node:fs/promises';\n\nimport {\n agent,\n execute,\n instructions,\n lmstudio,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, search_content_tool } from '@deepagents/toolbox';\n\nimport { type Outline, buildToc } from './outline-agent.ts';\n\ntype SectionAgentContext = {\n repo_path: string;\n scratchpad: string;\n tree: string;\n toc: string[];\n};\n\n// Agent for writing leaf sections\nconst sectionWriterAgent = agent<unknown, SectionAgentContext>({\n name: 'Section Writer',\n model: wrapLanguageModel({\n // model: groq('moonshotai/kimi-k2-instruct-0905'),\n model: lmstudio('openai/gpt-oss-20b'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.5 },\n }),\n }),\n tools: {\n read_file: read_file_tool,\n search_content: search_content_tool,\n },\n prompt: '',\n});\n\n// Agent for writing parent TOC pages\nconst tocPageAgent = agent<unknown, SectionAgentContext>({\n name: 'TOC Page Writer',\n model: wrapLanguageModel({\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n middleware: defaultSettingsMiddleware({\n settings: { temperature: 0.1 },\n }),\n }),\n prompt: instructions({\n purpose: [\n 'You create table-of-contents style pages for wiki parent sections.',\n 'Your pages introduce the parent topic and provide an organized overview of child sections.',\n ],\n routine: [\n 'Write a clear, engaging introduction to the parent section topic.',\n 'Provide context about what readers will learn in the child sections.',\n 'Create a structured overview that explains how child sections relate to each other.',\n 'Your content should help readers understand the big picture before diving into specifics.',\n 'Do NOT duplicate detailed content - that belongs in the child pages.',\n ],\n }),\n});\n\ntype WikiResult = {\n files: Record<string, string>; // section title -> file path\n index: string; // main index content\n};\n\n/**\n * Build file path for a section based on its hierarchical path\n * Example: ['Project Overview', 'Architecture'] -> 'docs/project_overview_architecture.md'\n */\nfunction buildFilePath(pathSegments: string[]): string {\n return `${snakeCase(pathSegments.join('_'))}.md`;\n}\n\n/**\n * Write content for a leaf section using the section writer agent\n */\nasync function writeSection(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing section: ${pathSegments.join(' > ')}`);\n\n const result = await execute(\n sectionWriterAgent,\n [\n user(\n `You are writing the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Use the provided tools to inspect relevant files in the repository\n2. Write clear, comprehensive, and accurate markdown content for this section\n3. Include code examples where appropriate\n4. Ensure the content is self-contained and valuable\n5. Focus specifically on the topic: ${item.title}\n\nWrite the section content now.\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Write a TOC-style page for a parent section\n */\nasync function writeTocPage(\n item: Outline[number],\n pathSegments: string[],\n childFiles: Array<{ title: string; path: string }>,\n state: SectionAgentContext,\n): Promise<string> {\n console.log(`Writing TOC page: ${pathSegments.join(' > ')}`);\n\n const childSummaries = childFiles\n .map((child, index) => `${index + 1}. **${child.title}**`)\n .join('\\n');\n\n const childLinks = childFiles\n .map((child) => `- [${child.title}](${child.path})`)\n .join('\\n');\n\n const result = await execute(\n tocPageAgent,\n [\n user(\n `You are creating a table-of-contents page for the section: ${item.title}\n\nFull path: ${pathSegments.join(' > ')}\n\nThis parent section has the following child sections:\n${childSummaries}\n\nThe complete wiki outline is:\n<WikiOutline>\n${state.toc.join('\\n')}\n</WikiOutline>\n\nThe repository structure is:\n<RepositoryTree>\n${state.tree}\n</RepositoryTree>\n\nYour task:\n1. Write a clear introduction to the \"${item.title}\" topic\n2. Explain what readers will learn from the child sections below\n3. Provide context about how these child sections relate to each other\n4. Keep it concise - this is a navigation page, not the full content\n\nAfter your introduction, you MUST include this exact navigation section:\n\n## Sections\n\n${childLinks}\n\nWrite the TOC page content now (introduction followed by the navigation section above).\n`,\n ),\n ],\n state,\n );\n\n return result.text;\n}\n\n/**\n * Recursively process outline items and generate markdown files\n */\nasync function processOutlineItem(\n item: Outline[number],\n pathSegments: string[],\n state: SectionAgentContext,\n files: Record<string, string>,\n): Promise<void> {\n const currentPath = [...pathSegments, item.title];\n const filePath = buildFilePath(currentPath);\n\n if (!item.sections || item.sections.length === 0) {\n // Leaf node - write comprehensive content\n const content = await writeSection(item, currentPath, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created: ${filePath}`);\n } else {\n // Parent node - process children first, then create TOC page\n const childFiles: Array<{ title: string; path: string }> = [];\n\n for (const child of item.sections) {\n await processOutlineItem(child, currentPath, state, files);\n const childPath = buildFilePath([...currentPath, child.title]);\n childFiles.push({ title: child.title, path: childPath });\n }\n\n // Create TOC page for parent\n const content = await writeTocPage(item, currentPath, childFiles, state);\n await writeFile(filePath, content, 'utf-8');\n files[item.title] = filePath;\n console.log(`\u2713 Created TOC: ${filePath}`);\n }\n}\n\n/**\n * Generate a complete multi-page wiki from an outline\n *\n * This function creates separate markdown files for each section:\n * - Leaf sections get comprehensive content written by agents\n * - Parent sections get TOC-style pages with introductions and links to children\n * - All files use flat naming with full hierarchical path\n */\nexport async function completeWiki(state: {\n repo_path: string;\n outline: Outline;\n tree: string;\n}): Promise<WikiResult> {\n const toc = buildToc(state.outline);\n const files: Record<string, string> = {};\n\n const agentContext: SectionAgentContext = {\n repo_path: state.repo_path,\n scratchpad: '## Scratchpad\\n\\n',\n tree: state.tree,\n toc,\n };\n\n console.log('Starting multi-page wiki generation...');\n\n // Process each top-level item\n for (const item of state.outline) {\n await processOutlineItem(item, [], agentContext, files);\n }\n\n // Create main index page\n const indexLinks = state.outline\n .map((item) => {\n const filePath = buildFilePath([item.title]);\n return `- [${item.title}](${filePath})`;\n })\n .join('\\n');\n\n const index = `# Wiki Index\n\nWelcome to the documentation. This wiki is organized into the following sections:\n\n${indexLinks}\n`;\n\n console.log(`\u2713 Complete! Generated ${Object.keys(files).length} pages`);\n\n return { files, index };\n}\n", "import { groq } from '@ai-sdk/groq';\nimport { type UIMessage, generateId, toUIMessageStream, tool } from 'ai';\nimport z from 'zod';\n\nimport {\n agent,\n execute,\n generate,\n instructions,\n user,\n} from '@deepagents/agent';\nimport { read_file_tool, scratchpad_tool } from '@deepagents/toolbox';\n\nconst BaseOutlineItem = z.object({\n title: z.string().trim().min(1, 'Title is required'),\n});\ntype OutlineItem = z.output<typeof BaseOutlineItem> & {\n sections?: z.output<typeof OutlineItemSchema>[];\n};\nconst OutlineItemSchema: z.ZodType<OutlineItem> = z.lazy(() =>\n BaseOutlineItem.extend({\n sections: z.array(OutlineItemSchema).optional(),\n }),\n);\nconst OutlineSchema = z.array(OutlineItemSchema);\nexport type Outline = z.output<typeof OutlineSchema>;\nexport type OutlineAgentContext = {\n repo_path: string;\n outline: z.output<typeof OutlineSchema>;\n scratchpad: string;\n tree: string;\n};\n\nexport const outlineAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n // model: lmstudio('qwen/qwen3-8b'),\n // model: lmstudio('openai/gpt-oss-20b'),\n\n // temperature: 0.1,\n prompt: (context) =>\n instructions({\n purpose: [\n \"You are wiki architect, meticulously analyzing a repository's structure and content to automatically generate a comprehensive, intelligent, and perfectly structured outline, laying the bedrock for exceptional documentation.\",\n '\\n',\n '<RepositoryTree>',\n context?.tree || '',\n '</RepositoryTree>',\n ],\n routine: [],\n // routine: [\n // 'Your primary tool for memory is your `scratchpad`. After every action, you MUST summarize your findings and add them to the scratchpad using the `update_scratchpad` tool.',\n // 'Systematically investigate key files and directories use `search_files`. For each finding add it as a new note to your scratchpad.',\n // 'When you read a file like `README.md` or `package.json`, do not keep the whole content in your head. Instead, summarize the important parts (like headings, dependencies, or scripts) and add that summary to your scratchpad.',\n // 'Continue this process of exploring, summarizing, and adding to your scratchpad until you are confident you have a full picture of the repository.',\n // 'Once you believe you have gathered enough information, your second-to-last step is to review your entire scratchpad to synthesize a plan for the final outline.',\n // 'Finally, based *only* on the information you have gathered in your scratchpad, generate the complete, detailed outline and store it using the `store_outline` tool. You must only call `store_outline` ONCE at the very end.',\n // ],\n }),\n tools: {\n read_file: read_file_tool,\n // read_dir: read_dir_tool,\n // search_files: search_files_tool,\n // file_exists: file_exists_tool,\n update_scratchpad: scratchpad_tool,\n store_outline: tool({\n description: `Use this tool to store the generated outline.\n\t\tThe outline should be a detailed hierarchical structure representing the sections and subsections of the repository documentation. In thory you can nest sections as deep as you want, but try to keep it to 4 levels deep maximum.\n\n\t\t## Example outline\n\t\t[\n\t\t\t{\n\t\t\t\t\"title\": \"xxxx\",\n\t\t\t\t\"sections\": [\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"yyyy\",\n\t\t\t\t\t\tsections: [\n\t\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\t\"title\": \"vvvv\",\n\t\t\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t]\n\t\t\t\t\t},\n\t\t\t\t\t{\n\t\t\t\t\t\t\"title\": \"gggg\",\n\t\t\t\t\t\t\"sections\": [...],\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t]\n\t\t\t`,\n inputSchema: z.object({\n outline: OutlineSchema,\n }),\n // execute: (\n // { outline },\n // { context }: ToolExecutionOptions<OutlineAgentContext>,\n // ) => {\n // // Store the outline in a file or database\n // console.log('Generated Outline:\\n', outline);\n // context.outline = outline;\n // return 'Outline stored successfully.';\n // },\n }),\n },\n});\n\nexport const outlineCondensedAgent = agent<unknown, OutlineAgentContext>({\n name: 'Outline Condensed Agent',\n model: groq('moonshotai/kimi-k2-instruct-0905'),\n prompt: instructions({\n purpose: [\n 'To intelligently condense and optimize an existing outline by merging redundant sections, removing overly granular subdivisions, and creating a more streamlined, maintainable documentation structure.',\n 'Your goal is to reduce complexity while preserving all essential information and maintaining logical hierarchy.',\n ],\n routine: [\n 'Examine the current outline structure stored in the context. Use your scratchpad to track your analysis.',\n 'Identify sections that are too granular (e.g., sections with only 1-2 subsections that could be merged with their parent).',\n 'Look for redundant or overlapping sections that cover similar topics and can be consolidated.',\n 'Note sections with excessive nesting depth (more than 3-4 levels) that could be flattened.',\n 'Identify sections with very similar titles that could be merged (e.g., \"API Overview\" and \"API Introduction\").',\n 'For each potential consolidation, add a note to your scratchpad explaining the rationale.',\n 'Create a condensed version of the outline that:',\n ' - Merges related subsections into broader topics',\n ' - Reduces nesting depth where appropriate',\n ' - Eliminates redundancy while keeping all unique content areas',\n ' - Maintains a maximum depth of 3 levels unless absolutely necessary',\n ' - Ensures each section has substantial content to document',\n 'Return the condensed outline as structured output.',\n ],\n }),\n output: OutlineSchema,\n});\n\nexport async function generateOutline(state: OutlineAgentContext) {\n const messages: UIMessage[] = [\n user(\n 'Walk through the repository and generate a detailed outline. Make sure to avoid looking into framework generated files and folders. when outline is complete, call the store_outline tool.',\n ),\n ];\n const max_iterations = 3;\n let current_iteration = 0;\n while (current_iteration < max_iterations) {\n console.log(`\\n=== Outline Iteration ${current_iteration + 1} ===\\n`);\n const result = await execute(outlineAgent, messages, state);\n await Array.fromAsync(\n toUIMessageStream({\n stream: result.stream,\n tools: outlineAgent.toToolset(),\n generateMessageId: generateId,\n originalMessages: messages,\n onEnd: async ({ responseMessage }: { responseMessage: UIMessage }) => {\n messages.push(responseMessage);\n },\n }),\n );\n await result.consumeStream();\n const calls = await result.toolCalls;\n const outlineCall = calls.find(\n (t: { toolName: string }) => t.toolName === 'store_outline',\n );\n if (outlineCall) {\n console.log('\\n=== Outline Generation Complete ===\\n');\n state.outline = outlineCall.input.outline;\n break;\n }\n current_iteration++;\n }\n if (!state.outline.length) {\n throw new Error('Outline generation failed.');\n }\n return generate(\n outlineCondensedAgent,\n `Condense and optimize the following outline:\\n\\n${buildToc(state.outline)}`,\n state,\n ).then(({ output }) => output);\n}\n\nfunction slugify(text: string) {\n return text\n .toLowerCase()\n .replace(/[^a-z0-9\\s-]/g, '')\n .trim()\n .replace(/\\s+/g, '-')\n .replace(/-+/g, '-');\n}\n\nexport function buildToc(\n items: OutlineItem[],\n baseDepth = 1,\n prefix: string[] = [],\n) {\n const lines: string[] = [];\n for (const it of items) {\n const path = [...prefix, it.title];\n const indent = ' '.repeat(Math.max(0, path.length - 1));\n const anchor = slugify(it.title);\n lines.push(`${indent}- [${it.title}](#${anchor})`);\n if (it.sections?.length) {\n lines.push(...buildToc(it.sections, baseDepth + 1, path));\n }\n }\n return lines;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["writeFile", "groq", "agent", "execute", "instructions", "user", "read_file_tool", "agent", "read_file_tool", "groq", "instructions", "state", "result", "execute", "user", "writeFile"]
|
|
7
7
|
}
|
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
type IgnoreAgentContext = {
|
|
2
2
|
repo_path: string;
|
|
3
|
-
}
|
|
3
|
+
};
|
|
4
|
+
export declare const ignoreAgent: import("@deepagents/agent").Agent<unknown, IgnoreAgentContext, IgnoreAgentContext>;
|
|
5
|
+
export {};
|
|
4
6
|
//# sourceMappingURL=gitignore-agent.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gitignore-agent.d.ts","sourceRoot":"","sources":["../../../src/lib/deepwiki/gitignore-agent.ts"],"names":[],"mappings":"AAOA,
|
|
1
|
+
{"version":3,"file":"gitignore-agent.d.ts","sourceRoot":"","sources":["../../../src/lib/deepwiki/gitignore-agent.ts"],"names":[],"mappings":"AAOA,KAAK,kBAAkB,GAAG;IAAE,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhD,eAAO,MAAM,WAAW,oFAoCtB,CAAC"}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
import { groq } from "@ai-sdk/groq";
|
|
3
3
|
import { tool } from "ai";
|
|
4
4
|
import z from "zod";
|
|
5
|
-
import { agent, instructions
|
|
5
|
+
import { agent, instructions } from "@deepagents/agent";
|
|
6
6
|
import { read_dir_tool, read_file_tool } from "@deepagents/toolbox";
|
|
7
7
|
var ignoreAgent = agent({
|
|
8
8
|
name: "Ignore Agent",
|
|
@@ -26,8 +26,7 @@ var ignoreAgent = agent({
|
|
|
26
26
|
inputSchema: z.object({
|
|
27
27
|
content: z.string().min(1).describe("The content of the .gitignore file.")
|
|
28
28
|
}),
|
|
29
|
-
execute: async ({ content },
|
|
30
|
-
const context = toState(options);
|
|
29
|
+
execute: async ({ content }, { context }) => {
|
|
31
30
|
console.log("Generated .gitignore content:\n", content);
|
|
32
31
|
return "Successfully wrote .gitignore file.";
|
|
33
32
|
}
|