@aigne/doc-smith 0.9.6-beta → 0.9.6-beta.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/CHANGELOG.md +7 -0
- package/agents/create/document-structure-tools/delete-document.mjs +32 -9
- package/agents/create/update-document-structure.yaml +1 -1
- package/agents/create/user-add-document/add-documents-to-structure.mjs +96 -0
- package/agents/create/user-add-document/find-documents-to-add-links.yaml +47 -0
- package/agents/create/user-add-document/index.yaml +46 -0
- package/agents/create/user-add-document/prepare-documents-to-translate.mjs +22 -0
- package/agents/create/user-add-document/print-add-document-summary.mjs +56 -0
- package/agents/create/user-add-document/review-documents-with-new-links.mjs +73 -0
- package/agents/create/user-remove-document/find-documents-with-invalid-links.mjs +67 -0
- package/agents/create/user-remove-document/index.yaml +41 -0
- package/agents/create/user-remove-document/prepare-documents-to-translate.mjs +22 -0
- package/agents/create/user-remove-document/print-remove-document-summary.mjs +56 -0
- package/agents/create/user-remove-document/remove-documents-from-structure.mjs +96 -0
- package/agents/create/user-remove-document/review-documents-with-invalid-links.mjs +116 -0
- package/agents/create/user-review-document-structure.mjs +1 -40
- package/agents/create/utils/init-current-content.mjs +38 -0
- package/agents/update/document-tools/update-document-content.mjs +12 -12
- package/agents/update/update-document-detail.yaml +5 -1
- package/agents/update/update-single/update-single-document-detail.mjs +21 -6
- package/agents/update/user-review-document.mjs +10 -13
- package/agents/utils/add-translates-to-structure.mjs +29 -0
- package/agents/utils/{analyze-feedback-intent.yaml → analyze-document-feedback-intent.yaml} +5 -2
- package/agents/utils/analyze-structure-feedback-intent.yaml +29 -0
- package/agents/utils/check-detail-result.mjs +2 -14
- package/aigne.yaml +10 -1
- package/package.json +1 -1
- package/prompts/structure/find-documents-to-add-links.md +52 -0
- package/prompts/utils/analyze-document-feedback-intent.md +54 -0
- package/prompts/utils/analyze-structure-feedback-intent.md +43 -0
- package/types/document-schema.mjs +2 -0
- package/types/document-structure-schema.mjs +6 -2
- package/utils/docs-finder-utils.mjs +82 -0
- package/utils/markdown-checker.mjs +50 -5
- package/utils/utils.mjs +103 -0
- package/prompts/utils/analyze-feedback-intent.md +0 -55
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Task: Find Documents to Add Links
|
|
2
|
+
|
|
3
|
+
Determine which existing documents should link to newly added documents.
|
|
4
|
+
|
|
5
|
+
## Input
|
|
6
|
+
|
|
7
|
+
<documentStructure>
|
|
8
|
+
{{originalDocumentStructure}}
|
|
9
|
+
</documentStructure>
|
|
10
|
+
|
|
11
|
+
<newDocuments>
|
|
12
|
+
{{newDocuments}}
|
|
13
|
+
</newDocuments>
|
|
14
|
+
|
|
15
|
+
<userFeedback>
|
|
16
|
+
{{allFeedback}}
|
|
17
|
+
</userFeedback>
|
|
18
|
+
|
|
19
|
+
## Steps
|
|
20
|
+
|
|
21
|
+
1. **Check <userFeedback> first.**
|
|
22
|
+
- If users explicitly specify linking (e.g., “link FAQ from About”), follow exactly.
|
|
23
|
+
2. **Analyze <documentStructure>.**
|
|
24
|
+
Identify existing documents that should link to those in <newDocuments> using the rules below.
|
|
25
|
+
3. For each qualifying document, add a non-empty `newLinks` array containing new document paths.
|
|
26
|
+
4. Output only these updated documents (subset of <documentStructure>) as `documentsWithNewLinks`.
|
|
27
|
+
|
|
28
|
+
Each item in `documentsWithNewLinks` must:
|
|
29
|
+
- Be an existing document from <documentStructure>
|
|
30
|
+
- Retain all original properties (`path`, `title`, `description`, `parentId`, `icon`, `sourceIds`)
|
|
31
|
+
- Include `newLinks: string[]`
|
|
32
|
+
|
|
33
|
+
## Linking Rules (in priority order)
|
|
34
|
+
|
|
35
|
+
1. **User Instructions** — Follow explicit <userFeedback>.
|
|
36
|
+
2. **Parent–Child** — If a new document’s `parentId` equals a document’s `path`, the parent links to it.
|
|
37
|
+
3. **Semantic Similarity** — Link thematically related documents (e.g., “About” ↔ “Team”).
|
|
38
|
+
4. **Navigation Context** — Documents in the same navigation group may link.
|
|
39
|
+
5. **Hierarchy** — Sibling or section documents may cross-link.
|
|
40
|
+
6. **Relevance** — Add links only when it improves navigation logically.
|
|
41
|
+
|
|
42
|
+
## Output Format
|
|
43
|
+
|
|
44
|
+
```json
|
|
45
|
+
{
|
|
46
|
+
"documentsWithNewLinks": [
|
|
47
|
+
{
|
|
48
|
+
"path": "/existing-document",
|
|
49
|
+
"newLinks": ["/new-document-1", "/new-document-2"]
|
|
50
|
+
}
|
|
51
|
+
]
|
|
52
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<role>
|
|
2
|
+
You are a feedback intent analyzer for **document content modifications**. Your task is to determine the intent type of user feedback regarding content-level operations inside a document, and whether external data sources are needed.
|
|
3
|
+
</role>
|
|
4
|
+
|
|
5
|
+
<input>
|
|
6
|
+
feedback: {{feedback}}
|
|
7
|
+
</input>
|
|
8
|
+
|
|
9
|
+
<analysis_rules>
|
|
10
|
+
If the feedback contains any document-level (structure) operations, return an error (document content edits cannot include structure changes).
|
|
11
|
+
|
|
12
|
+
Scope: Only analyze feedback related to document content (e.g. sections, text, images).
|
|
13
|
+
|
|
14
|
+
**Intent types:**
|
|
15
|
+
|
|
16
|
+
1. add - Adding new sections or content inside a document
|
|
17
|
+
2. edit - Modifying existing content, titles, descriptions, components
|
|
18
|
+
3. delete - Removing sections or content
|
|
19
|
+
4. move - Moving sections to different positions within the document
|
|
20
|
+
5. reorder - Changing the order of sections at the same level
|
|
21
|
+
6. mixed - Combination of multiple intent types
|
|
22
|
+
|
|
23
|
+
**Data source rules:**
|
|
24
|
+
|
|
25
|
+
- add/edit -> needDataSources = true
|
|
26
|
+
- delete/move/reorder -> needDataSources = false
|
|
27
|
+
- mixed -> needDataSources = true if any add/edit is included
|
|
28
|
+
|
|
29
|
+
**Decision logic:**
|
|
30
|
+
|
|
31
|
+
- Only consider document content operations.
|
|
32
|
+
- If any add or edit operation exists -> needDataSources = true
|
|
33
|
+
- If only delete, move, or reorder operations exist -> needDataSources = false
|
|
34
|
+
- When uncertain, default to needDataSources = true
|
|
35
|
+
</analysis_rules>
|
|
36
|
+
|
|
37
|
+
<output_rules>
|
|
38
|
+
Normal output:
|
|
39
|
+
|
|
40
|
+
{
|
|
41
|
+
"error": false,
|
|
42
|
+
"needDataSources": boolean,
|
|
43
|
+
"intentType": "add" | "edit" | "delete" | "move" | "reorder" | "mixed",
|
|
44
|
+
"reason": "Explanation of why data sources are or aren't needed based on page content operations."
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
Error output (if document-level operations are detected):
|
|
48
|
+
|
|
49
|
+
{
|
|
50
|
+
"error": true,
|
|
51
|
+
"needDataSources": false,
|
|
52
|
+
"reason": "Feedback mixes document-content edits with document-structure operations. When analyzing document content, structure changes are not allowed. Please split into separate feedback items."
|
|
53
|
+
}
|
|
54
|
+
</output_rules>
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
<role>
|
|
2
|
+
You are a feedback intent analyzer for **document structure modifications**. Your task is to determine the intent type of user feedback regarding document-level operations and whether external data sources are needed.
|
|
3
|
+
</role>
|
|
4
|
+
|
|
5
|
+
<input>
|
|
6
|
+
feedback: {{feedback}}
|
|
7
|
+
</input>
|
|
8
|
+
|
|
9
|
+
<analysis_rules>
|
|
10
|
+
Scope: Only analyze feedback related to document structure. Ignore any content-level operations inside document (e.g. sections, text, images).
|
|
11
|
+
|
|
12
|
+
**intent types:**
|
|
13
|
+
|
|
14
|
+
1. add - Adding new documents
|
|
15
|
+
2. edit - Modifying document-level properties (e.g., path, parentId, title of the document itself)
|
|
16
|
+
3. delete - Removing documents
|
|
17
|
+
4. move - Moving documents to different positions or parent sections
|
|
18
|
+
5. reorder - Changing the order of documents
|
|
19
|
+
6. mixed - Combination of multiple intent types
|
|
20
|
+
|
|
21
|
+
**Data source rules:**
|
|
22
|
+
|
|
23
|
+
- add/edit -> needDataSources = true
|
|
24
|
+
- delete/move/reorder -> needDataSources = false
|
|
25
|
+
- mixed -> needDataSources = true if any add/edit is included
|
|
26
|
+
|
|
27
|
+
**Decision logic:**
|
|
28
|
+
|
|
29
|
+
- Only consider document-level operations in the feedback.
|
|
30
|
+
- If any add or edit operation exists -> needDataSources = true
|
|
31
|
+
- If only delete, move, or reorder operations exist -> needDataSources = false
|
|
32
|
+
- When uncertain, default to needDataSources = true
|
|
33
|
+
</analysis_rules>
|
|
34
|
+
|
|
35
|
+
<output_rules>
|
|
36
|
+
Return a JSON object:
|
|
37
|
+
|
|
38
|
+
{
|
|
39
|
+
"needDataSources": boolean,
|
|
40
|
+
"intentType": "add" | "edit" | "delete" | "move" | "reorder" | "mixed",
|
|
41
|
+
"reason": "Explanation of why data sources are or aren't needed based on document-level operations."
|
|
42
|
+
}
|
|
43
|
+
</output_rules>
|
|
@@ -4,6 +4,7 @@ import { zodToJsonSchema } from "zod-to-json-schema";
|
|
|
4
4
|
// Update document content schemas
|
|
5
5
|
export const updateDocumentContentInputSchema = z.object({
|
|
6
6
|
diffPatch: z.string().min(1, "Diff patch is required"),
|
|
7
|
+
path: z.string().min(1, "Path is required for concurrent document updates"),
|
|
7
8
|
});
|
|
8
9
|
|
|
9
10
|
export const updateDocumentContentOutputSchema = z.object({
|
|
@@ -18,6 +19,7 @@ export const getUpdateDocumentContentInputJsonSchema = () => {
|
|
|
18
19
|
const schema = zodToJsonSchema(updateDocumentContentInputSchema);
|
|
19
20
|
if (schema.properties) {
|
|
20
21
|
schema.properties.diffPatch.description = "Diff patch string to apply to the original content";
|
|
22
|
+
schema.properties.path.description = "Document path";
|
|
21
23
|
}
|
|
22
24
|
return schema;
|
|
23
25
|
};
|
|
@@ -33,12 +33,13 @@ export const addDocumentOutputSchema = z.object({
|
|
|
33
33
|
// Delete document schemas
|
|
34
34
|
export const deleteDocumentInputSchema = z.object({
|
|
35
35
|
path: z.string().min(1, "Path is required"),
|
|
36
|
+
recursive: z.boolean().optional(),
|
|
36
37
|
});
|
|
37
38
|
|
|
38
39
|
export const deleteDocumentOutputSchema = z.object({
|
|
39
40
|
documentStructure: documentStructureSchema,
|
|
40
41
|
message: z.string().optional(),
|
|
41
|
-
|
|
42
|
+
deletedDocuments: z.array(documentItemSchema).optional(),
|
|
42
43
|
error: z.object({ message: z.string() }).optional(),
|
|
43
44
|
});
|
|
44
45
|
|
|
@@ -113,6 +114,8 @@ export const getDeleteDocumentInputJsonSchema = () => {
|
|
|
113
114
|
const schema = zodToJsonSchema(deleteDocumentInputSchema);
|
|
114
115
|
if (schema.properties) {
|
|
115
116
|
schema.properties.path.description = "URL path of the document to delete";
|
|
117
|
+
schema.properties.recursive.description =
|
|
118
|
+
"If true, recursively delete all child documents. If false or not provided, deletion will fail if child documents exist.";
|
|
116
119
|
}
|
|
117
120
|
return schema;
|
|
118
121
|
};
|
|
@@ -123,7 +126,8 @@ export const getDeleteDocumentOutputJsonSchema = () => {
|
|
|
123
126
|
schema.properties.documentStructure.description =
|
|
124
127
|
"Updated documentation structure array with the document removed";
|
|
125
128
|
schema.properties.message.description = "Success message describing the operation result";
|
|
126
|
-
schema.properties.
|
|
129
|
+
schema.properties.deletedDocuments.description =
|
|
130
|
+
"Array of deleted document objects (includes all recursively deleted child documents if recursive=true)";
|
|
127
131
|
schema.properties.error.description =
|
|
128
132
|
"Error object containing error message if operation failed";
|
|
129
133
|
}
|
|
@@ -324,6 +324,40 @@ export async function loadDocumentStructure(outputDir) {
|
|
|
324
324
|
}
|
|
325
325
|
}
|
|
326
326
|
|
|
327
|
+
/**
|
|
328
|
+
* Build allowed links set from document structure
|
|
329
|
+
* Includes both original paths and processed .md paths for link validation
|
|
330
|
+
* @param {Array} documentStructure - Array of documentation structure items with path property
|
|
331
|
+
* @returns {Set<string>} Set of allowed link paths
|
|
332
|
+
*/
|
|
333
|
+
export function buildAllowedLinksFromStructure(documentStructure) {
|
|
334
|
+
const allowedLinks = new Set();
|
|
335
|
+
|
|
336
|
+
if (!Array.isArray(documentStructure)) {
|
|
337
|
+
return allowedLinks;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
documentStructure.forEach((item) => {
|
|
341
|
+
if (!item?.path) {
|
|
342
|
+
return;
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
// Add original path
|
|
346
|
+
allowedLinks.add(item.path);
|
|
347
|
+
|
|
348
|
+
// Add processed .md path (same logic as processContent in utils.mjs)
|
|
349
|
+
let processedPath = item.path;
|
|
350
|
+
if (processedPath.startsWith(".")) {
|
|
351
|
+
processedPath = processedPath.replace(/^\./, "");
|
|
352
|
+
}
|
|
353
|
+
let flatPath = processedPath.replace(/^\//, "").replace(/\//g, "-");
|
|
354
|
+
flatPath = `./${flatPath}.md`;
|
|
355
|
+
allowedLinks.add(flatPath);
|
|
356
|
+
});
|
|
357
|
+
|
|
358
|
+
return allowedLinks;
|
|
359
|
+
}
|
|
360
|
+
|
|
327
361
|
/**
|
|
328
362
|
* Build a tree structure from a flat document structure array using parentId
|
|
329
363
|
* @param {Array} documentStructure - Flat array of document structure items with path and parentId
|
|
@@ -358,3 +392,51 @@ export function buildDocumentTree(documentStructure) {
|
|
|
358
392
|
|
|
359
393
|
return { rootNodes, nodeMap };
|
|
360
394
|
}
|
|
395
|
+
|
|
396
|
+
/**
|
|
397
|
+
* Format document structure for printing
|
|
398
|
+
* @param {Array} structure - Document structure array
|
|
399
|
+
* @returns {Object} Object containing rootNodes and printNode function
|
|
400
|
+
*/
|
|
401
|
+
function formatDocumentStructure(structure) {
|
|
402
|
+
const { rootNodes } = buildDocumentTree(structure);
|
|
403
|
+
|
|
404
|
+
function printNode(node, depth = 0) {
|
|
405
|
+
const INDENT_SPACES = " ";
|
|
406
|
+
const FOLDER_ICON = " 📁";
|
|
407
|
+
const FILE_ICON = " 📄";
|
|
408
|
+
const indent = INDENT_SPACES.repeat(depth);
|
|
409
|
+
const prefix = depth === 0 ? FOLDER_ICON : FILE_ICON;
|
|
410
|
+
|
|
411
|
+
console.log(`${indent}${prefix} ${node.title}`);
|
|
412
|
+
|
|
413
|
+
if (node.children && node.children.length > 0) {
|
|
414
|
+
node.children.forEach((child) => {
|
|
415
|
+
printNode(child, depth + 1);
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
return { rootNodes, printNode };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
/**
|
|
424
|
+
* Print document structure in a user-friendly format
|
|
425
|
+
* @param {Array} structure - Document structure array
|
|
426
|
+
*/
|
|
427
|
+
export function printDocumentStructure(structure) {
|
|
428
|
+
console.log(`\n ${"-".repeat(50)}`);
|
|
429
|
+
console.log(" Current Documentation Structure");
|
|
430
|
+
console.log(` ${"-".repeat(50)}`);
|
|
431
|
+
|
|
432
|
+
const { rootNodes, printNode } = formatDocumentStructure(structure);
|
|
433
|
+
|
|
434
|
+
if (rootNodes.length === 0) {
|
|
435
|
+
console.log(" No documentation structure found.");
|
|
436
|
+
} else {
|
|
437
|
+
rootNodes.forEach((node) => {
|
|
438
|
+
printNode(node);
|
|
439
|
+
});
|
|
440
|
+
}
|
|
441
|
+
console.log();
|
|
442
|
+
}
|
|
@@ -59,6 +59,9 @@ function countTableColumns(line) {
|
|
|
59
59
|
return columns.length;
|
|
60
60
|
}
|
|
61
61
|
|
|
62
|
+
const linkPattern = /(?<!!)\[([^\]]+)\]\(([^)]+)\)/g;
|
|
63
|
+
const hrefPattern = /<x-card[^>]*\s+data-href\s*=\s*(?:"([^"]+)"|'([^']+)'|([^\s>]+))/gi;
|
|
64
|
+
|
|
62
65
|
/**
|
|
63
66
|
* Check for dead links in markdown content
|
|
64
67
|
* @param {string} markdown - The markdown content
|
|
@@ -67,16 +70,33 @@ function countTableColumns(line) {
|
|
|
67
70
|
* @param {Array} errorMessages - Array to push error messages to
|
|
68
71
|
*/
|
|
69
72
|
function checkDeadLinks(markdown, source, allowedLinks, errorMessages) {
|
|
70
|
-
const
|
|
71
|
-
let match;
|
|
73
|
+
const links = [];
|
|
72
74
|
|
|
75
|
+
// Collect Markdown format links: [text](link)
|
|
76
|
+
const linkRegex = new RegExp(linkPattern.source, linkPattern.flags);
|
|
77
|
+
let match;
|
|
73
78
|
while (true) {
|
|
74
79
|
match = linkRegex.exec(markdown);
|
|
75
80
|
if (match === null) break;
|
|
81
|
+
links.push({ trimLink: match[2].trim(), display: `[${match[1]}](${match[2].trim()})` });
|
|
82
|
+
}
|
|
76
83
|
|
|
77
|
-
|
|
78
|
-
|
|
84
|
+
// Collect data-href attribute values from <x-card> elements
|
|
85
|
+
const hrefRegex = new RegExp(hrefPattern.source, hrefPattern.flags);
|
|
86
|
+
let attrMatch;
|
|
87
|
+
while (true) {
|
|
88
|
+
attrMatch = hrefRegex.exec(markdown);
|
|
89
|
+
if (attrMatch === null) break;
|
|
90
|
+
const attrValue = (attrMatch[1] || attrMatch[2] || attrMatch[3] || "").trim();
|
|
91
|
+
if (attrValue) {
|
|
92
|
+
// Preserve original format with quotes if present
|
|
93
|
+
const originalMatch = attrMatch[0];
|
|
94
|
+
links.push({ trimLink: attrValue, display: originalMatch });
|
|
95
|
+
}
|
|
96
|
+
}
|
|
79
97
|
|
|
98
|
+
// Process all collected links with the same logic
|
|
99
|
+
for (const { trimLink, display } of links) {
|
|
80
100
|
// Only check links that processContent would process
|
|
81
101
|
// Exclude external links and mailto
|
|
82
102
|
if (/^(https?:\/\/|mailto:)/.test(trimLink)) continue;
|
|
@@ -90,12 +110,37 @@ function checkDeadLinks(markdown, source, allowedLinks, errorMessages) {
|
|
|
90
110
|
// Check if this link is in the allowed links set
|
|
91
111
|
if (!allowedLinks.has(path)) {
|
|
92
112
|
errorMessages.push(
|
|
93
|
-
`Found a dead link in ${source}:
|
|
113
|
+
`Found a dead link in ${source}: ${display}, ensure the link exists in the documentation structure path`,
|
|
94
114
|
);
|
|
95
115
|
}
|
|
96
116
|
}
|
|
97
117
|
}
|
|
98
118
|
|
|
119
|
+
/**
|
|
120
|
+
* Extract link from error message
|
|
121
|
+
* @param {string} error - The error message
|
|
122
|
+
* @returns {string} - The link
|
|
123
|
+
*/
|
|
124
|
+
export function getLinkFromError(error) {
|
|
125
|
+
if (!error || !error.includes("Found a dead link in")) {
|
|
126
|
+
return "";
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
const linkRegex = new RegExp(linkPattern.source, linkPattern.flags);
|
|
130
|
+
let match = linkRegex.exec(error);
|
|
131
|
+
if (match) {
|
|
132
|
+
return match[2].trim();
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
const hrefRegex = new RegExp(hrefPattern.source, hrefPattern.flags);
|
|
136
|
+
match = hrefRegex.exec(error);
|
|
137
|
+
if (match) {
|
|
138
|
+
return (match[1] || match[2] || match[3] || "").trim();
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return "";
|
|
142
|
+
}
|
|
143
|
+
|
|
99
144
|
/**
|
|
100
145
|
* Check code block content for indentation consistency issues
|
|
101
146
|
* @param {Array} codeBlockContent - Array of {line, lineNumber} objects from the code block
|
package/utils/utils.mjs
CHANGED
|
@@ -1225,3 +1225,106 @@ export function getContentHash(str, { trim = true } = {}) {
|
|
|
1225
1225
|
const input = trim && typeof str === "string" ? str.trim() : str;
|
|
1226
1226
|
return crypto.createHash("sha256").update(input).digest("hex");
|
|
1227
1227
|
}
|
|
1228
|
+
|
|
1229
|
+
function toPath(path) {
|
|
1230
|
+
if (Array.isArray(path)) return path;
|
|
1231
|
+
|
|
1232
|
+
const result = [];
|
|
1233
|
+
path.replace(/[^.[\]]+|\[(\d+|(["'])(.*?)\2)\]/g, (match, bracketContent, quote, quotedKey) => {
|
|
1234
|
+
if (quote) {
|
|
1235
|
+
// ["key"] or ['key']
|
|
1236
|
+
result.push(quotedKey);
|
|
1237
|
+
} else if (bracketContent !== undefined) {
|
|
1238
|
+
// [123]
|
|
1239
|
+
result.push(bracketContent);
|
|
1240
|
+
} else {
|
|
1241
|
+
// dot notation
|
|
1242
|
+
result.push(match);
|
|
1243
|
+
}
|
|
1244
|
+
});
|
|
1245
|
+
return result;
|
|
1246
|
+
}
|
|
1247
|
+
|
|
1248
|
+
/**
|
|
1249
|
+
* Deeply get the value at a given path from an object, or return a default value if missing.
|
|
1250
|
+
* @param {object} obj - The object to query.
|
|
1251
|
+
* @param {string|Array<string|number>} path - The path to get, as a string or array.
|
|
1252
|
+
* @param {*} defaultValue - The value returned if the resolved value is undefined.
|
|
1253
|
+
* @returns {*} The value at the path or defaultValue.
|
|
1254
|
+
*/
|
|
1255
|
+
export function dget(obj, path, defaultValue) {
|
|
1256
|
+
const parts = toPath(path);
|
|
1257
|
+
|
|
1258
|
+
let current = obj;
|
|
1259
|
+
for (const key of parts) {
|
|
1260
|
+
if (current == null || !(key in current)) return defaultValue;
|
|
1261
|
+
current = current[key];
|
|
1262
|
+
}
|
|
1263
|
+
return current;
|
|
1264
|
+
}
|
|
1265
|
+
|
|
1266
|
+
/**
|
|
1267
|
+
* Deeply set the value at a given path in an object.
|
|
1268
|
+
* @param {object} obj - The object to modify.
|
|
1269
|
+
* @param {string|Array<string|number>} path - The path to set, as a string or array.
|
|
1270
|
+
* @param {*} value - The value to set.
|
|
1271
|
+
* @returns {object} The modified object.
|
|
1272
|
+
*/
|
|
1273
|
+
export function dset(obj, path, value) {
|
|
1274
|
+
const parts = toPath(path);
|
|
1275
|
+
|
|
1276
|
+
let current = obj;
|
|
1277
|
+
for (let i = 0; i < parts.length; i++) {
|
|
1278
|
+
const key = parts[i];
|
|
1279
|
+
|
|
1280
|
+
if (i === parts.length - 1) {
|
|
1281
|
+
current[key] = value;
|
|
1282
|
+
} else {
|
|
1283
|
+
if (current[key] == null || typeof current[key] !== "object") {
|
|
1284
|
+
current[key] = String(parts[i + 1]).match(/^\d+$/) ? [] : {};
|
|
1285
|
+
}
|
|
1286
|
+
current = current[key];
|
|
1287
|
+
}
|
|
1288
|
+
}
|
|
1289
|
+
return obj;
|
|
1290
|
+
}
|
|
1291
|
+
|
|
1292
|
+
/**
|
|
1293
|
+
* Create a context path manager that provides get/set/clear operations
|
|
1294
|
+
* @param {object} options - The options object containing user context
|
|
1295
|
+
* @param {string} path - The context path (e.g., 'currentPageDetails./about' or 'lastToolInputs./about')
|
|
1296
|
+
* @returns {object} An object with { get, set } methods and a contextPath method for sub-paths
|
|
1297
|
+
*/
|
|
1298
|
+
export function userContextAt(options, path) {
|
|
1299
|
+
const userContext = options?.context?.userContext || null;
|
|
1300
|
+
if (!userContext) {
|
|
1301
|
+
throw new Error("userContext is not available");
|
|
1302
|
+
}
|
|
1303
|
+
|
|
1304
|
+
return {
|
|
1305
|
+
/**
|
|
1306
|
+
* Get a value from the context path
|
|
1307
|
+
* @param {string} [key] - Optional key for nested access (e.g., 'updateMeta' for lastToolInputs)
|
|
1308
|
+
* @returns {*} The value at the path, or undefined if not found
|
|
1309
|
+
*/
|
|
1310
|
+
get(key) {
|
|
1311
|
+
if (key !== undefined) {
|
|
1312
|
+
return dget(userContext, `${path}.${key}`);
|
|
1313
|
+
}
|
|
1314
|
+
return dget(userContext, path);
|
|
1315
|
+
},
|
|
1316
|
+
|
|
1317
|
+
/**
|
|
1318
|
+
* Set a value in the context path
|
|
1319
|
+
* @param {string|*} key - If key is provided, this is the key; otherwise this is the value
|
|
1320
|
+
* @param {*} [value] - The value to set (required if first param is a key)
|
|
1321
|
+
*/
|
|
1322
|
+
set(key, value) {
|
|
1323
|
+
if (value !== undefined) {
|
|
1324
|
+
dset(userContext, `${path}.${key}`, value);
|
|
1325
|
+
} else {
|
|
1326
|
+
dset(userContext, path, key);
|
|
1327
|
+
}
|
|
1328
|
+
},
|
|
1329
|
+
};
|
|
1330
|
+
}
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
<role>
|
|
2
|
-
You are a feedback intent analyzer. Your task is to determine whether data sources are needed to fulfill the user's feedback about content modifications.
|
|
3
|
-
</role>
|
|
4
|
-
|
|
5
|
-
<input>
|
|
6
|
-
- feedback: {{feedback}}
|
|
7
|
-
</input>
|
|
8
|
-
|
|
9
|
-
<analysis_rules>
|
|
10
|
-
**Determining Data Source Necessity:**
|
|
11
|
-
|
|
12
|
-
You need to analyze the user's feedback and categorize it into different intent types. Based on the intent type, determine if data sources are required.
|
|
13
|
-
|
|
14
|
-
This analyzer is generic and can be used for any content modification scenarios (documentation structure, document content, translations, etc.).
|
|
15
|
-
|
|
16
|
-
**Intent Types:**
|
|
17
|
-
|
|
18
|
-
1. **add** - Adding new items, sections, or content
|
|
19
|
-
- Requires data sources: **YES**
|
|
20
|
-
- Reason: Need sufficient context from codebase or related materials to generate accurate new content
|
|
21
|
-
|
|
22
|
-
2. **edit** - Modifying existing content, descriptions, titles, or properties
|
|
23
|
-
- Requires data sources: **YES**
|
|
24
|
-
- Reason: Need context to ensure modifications are accurate and contextually appropriate
|
|
25
|
-
|
|
26
|
-
3. **delete** - Removing items, sections, or content
|
|
27
|
-
- Requires data sources: **NO**
|
|
28
|
-
- Reason: Deletion only needs to identify what to remove, no new content generation needed
|
|
29
|
-
|
|
30
|
-
4. **move** - Moving items to different positions or parent sections
|
|
31
|
-
- Requires data sources: **NO**
|
|
32
|
-
- Reason: Only changing item location in the structure, no content changes needed
|
|
33
|
-
|
|
34
|
-
5. **reorder** - Changing the order of items at the same level
|
|
35
|
-
- Requires data sources: **NO**
|
|
36
|
-
- Reason: Only rearranging sequence, no content generation needed
|
|
37
|
-
|
|
38
|
-
6. **mixed** - Combination of multiple intent types
|
|
39
|
-
- Requires data sources: **Depends on whether add/edit operations are included**
|
|
40
|
-
- Reason: If the feedback includes any add or edit operations, data sources are needed
|
|
41
|
-
|
|
42
|
-
**Decision Logic:**
|
|
43
|
-
- If the feedback contains ANY add or edit operations → `needDataSources = true`
|
|
44
|
-
- If the feedback ONLY contains delete, move, or reorder operations → `needDataSources = false`
|
|
45
|
-
- When in doubt, default to `needDataSources = true` to ensure sufficient context
|
|
46
|
-
</analysis_rules>
|
|
47
|
-
|
|
48
|
-
<output_rules>
|
|
49
|
-
Return a JSON object with:
|
|
50
|
-
- `needDataSources`: boolean indicating if data sources are required
|
|
51
|
-
- `intentType`: the primary intent type (add, edit, delete, move, reorder, or mixed)
|
|
52
|
-
- `reason`: clear explanation of why data sources are or aren't needed
|
|
53
|
-
|
|
54
|
-
Analyze the feedback carefully and be conservative - when uncertain, prefer `needDataSources: true` to ensure sufficient context is available.
|
|
55
|
-
</output_rules>
|