@fluidframework/tree-agent 2.70.0-360753 → 2.70.0-361248
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/api-report/tree-agent.alpha.api.md +2 -2
- package/dist/agent.d.ts +4 -4
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +25 -0
- package/dist/agent.js.map +1 -1
- package/dist/api.d.ts +66 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js.map +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +111 -17
- package/dist/prompt.js.map +1 -1
- package/lib/agent.d.ts +4 -4
- package/lib/agent.d.ts.map +1 -1
- package/lib/agent.js +26 -1
- package/lib/agent.js.map +1 -1
- package/lib/api.d.ts +66 -0
- package/lib/api.d.ts.map +1 -1
- package/lib/api.js.map +1 -1
- package/lib/prompt.d.ts.map +1 -1
- package/lib/prompt.js +110 -16
- package/lib/prompt.js.map +1 -1
- package/package.json +12 -12
- package/src/agent.ts +34 -8
- package/src/api.ts +73 -0
- package/src/prompt.ts +118 -18
package/src/prompt.ts
CHANGED
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
* Licensed under the MIT License.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
+
import { oob } from "@fluidframework/core-utils/internal";
|
|
6
7
|
import { NodeKind, Tree, TreeNode } from "@fluidframework/tree";
|
|
7
8
|
import type { ImplicitFieldSchema, TreeMapNode } from "@fluidframework/tree";
|
|
8
9
|
import type { ReadableField } from "@fluidframework/tree/alpha";
|
|
@@ -34,10 +35,20 @@ export function getPrompt<TRoot extends ImplicitFieldSchema>(args: {
|
|
|
34
35
|
const mapInterfaceName = "TreeMap";
|
|
35
36
|
const simpleSchema = getSimpleSchema(schema);
|
|
36
37
|
// Inspect the schema to determine what kinds of nodes are possible - this will affect how much information we need to include in the prompt.
|
|
38
|
+
const rootTypes = [...normalizeFieldSchema(schema).allowedTypeSet];
|
|
39
|
+
const rootTypeUnion = `${rootTypes.map((t) => getFriendlyName(t)).join(" | ")}`;
|
|
40
|
+
let nodeTypeUnion: string | undefined;
|
|
37
41
|
let hasArrays = false;
|
|
38
42
|
let hasMaps = false;
|
|
39
43
|
let exampleObjectName: string | undefined;
|
|
40
44
|
for (const [definition, nodeSchema] of simpleSchema.definitions) {
|
|
45
|
+
if (nodeSchema.kind !== NodeKind.Leaf) {
|
|
46
|
+
nodeTypeUnion =
|
|
47
|
+
nodeTypeUnion === undefined
|
|
48
|
+
? unqualifySchema(definition)
|
|
49
|
+
: `${nodeTypeUnion} | ${unqualifySchema(definition)}`;
|
|
50
|
+
}
|
|
51
|
+
|
|
41
52
|
switch (nodeSchema.kind) {
|
|
42
53
|
case NodeKind.Array: {
|
|
43
54
|
hasArrays = true;
|
|
@@ -68,25 +79,111 @@ export function getPrompt<TRoot extends ImplicitFieldSchema>(args: {
|
|
|
68
79
|
const stringified = stringifyTree(field);
|
|
69
80
|
const details: SchemaDetails = { hasHelperMethods: false };
|
|
70
81
|
const typescriptSchemaTypes = getZodSchemaAsTypeScript(domainTypes, details);
|
|
82
|
+
const exampleTypeName =
|
|
83
|
+
nodeTypeUnion === undefined
|
|
84
|
+
? undefined
|
|
85
|
+
: nodeTypeUnion
|
|
86
|
+
.split("|")
|
|
87
|
+
.map((part) => part.trim())
|
|
88
|
+
.find((part) => part.length > 0);
|
|
89
|
+
|
|
90
|
+
const createDocs =
|
|
91
|
+
exampleObjectName === undefined
|
|
92
|
+
? ""
|
|
93
|
+
: `\n /**
|
|
94
|
+
* A collection of builder functions for creating new tree nodes.
|
|
95
|
+
* @remarks
|
|
96
|
+
* Each property on this object is named after a type in the tree schema.
|
|
97
|
+
* Call the corresponding function to create a new node of that type.
|
|
98
|
+
* Always use these builder functions when creating new nodes rather than plain JavaScript objects.
|
|
99
|
+
*
|
|
100
|
+
* For example:
|
|
101
|
+
*
|
|
102
|
+
* \`\`\`javascript
|
|
103
|
+
* // This creates a new ${exampleObjectName} object:
|
|
104
|
+
* const ${communize(exampleObjectName)} = context.create.${exampleObjectName}({ ...properties });
|
|
105
|
+
* // Don't do this:
|
|
106
|
+
* // const ${communize(exampleObjectName)} = { ...properties };
|
|
107
|
+
* \`\`\`
|
|
108
|
+
*/
|
|
109
|
+
create: Record<string, <T extends TreeData>(input: T) => T>;\n`;
|
|
110
|
+
|
|
111
|
+
const isDocs =
|
|
112
|
+
exampleTypeName === undefined
|
|
113
|
+
? ""
|
|
114
|
+
: `\n /**
|
|
115
|
+
* A collection of type-guard functions for data in the tree.
|
|
116
|
+
* @remarks
|
|
117
|
+
* Each property on this object is named after a type in the tree schema.
|
|
118
|
+
* Call the corresponding function to check if a node is of that specific type.
|
|
119
|
+
* This is useful when working with nodes that could be one of multiple types.
|
|
120
|
+
*
|
|
121
|
+
* ${`Example: Check if a node is a ${exampleTypeName} with \`if (context.is.${exampleTypeName}(node)) {}\``}
|
|
122
|
+
*/
|
|
123
|
+
is: Record<string, <T extends TreeData>(data: unknown) => data is T>;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* Checks if the provided data is an array.
|
|
127
|
+
* @remarks
|
|
128
|
+
* DO NOT use \`Array.isArray\` to check if tree data is an array - use this function instead.
|
|
129
|
+
*
|
|
130
|
+
* This function will also work for native JavaScript arrays.
|
|
131
|
+
*
|
|
132
|
+
* ${`Example: \`if (context.isArray(node)) {}\``}
|
|
133
|
+
*/
|
|
134
|
+
isArray(data: any): boolean;
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Checks if the provided data is a map.
|
|
138
|
+
* @remarks
|
|
139
|
+
* DO NOT use \`instanceof Map\` to check if tree data is a map - use this function instead.
|
|
140
|
+
*
|
|
141
|
+
* This function will also work for native JavaScript Map instances.
|
|
142
|
+
*
|
|
143
|
+
* ${`Example: \`if (context.isMap(node)) {}\``}
|
|
144
|
+
*/
|
|
145
|
+
isMap(data: any): boolean;\n`;
|
|
146
|
+
|
|
147
|
+
const context = `\`\`\`typescript
|
|
148
|
+
${nodeTypeUnion === undefined ? "" : `type TreeData = ${nodeTypeUnion};\n\n`} /**
|
|
149
|
+
* An object available to generated code which provides read and write access to the tree as well as utilities for creating and inspecting data in the tree.
|
|
150
|
+
* @remarks This object is available as a variable named \`context\` in the scope of the generated JavaScript snippet.
|
|
151
|
+
*/
|
|
152
|
+
interface Context<TSchema extends ImplicitFieldSchema> {
|
|
153
|
+
/**
|
|
154
|
+
* The root of the tree that can be read or mutated.
|
|
155
|
+
* @remarks
|
|
156
|
+
* You can read properties and navigate through the tree starting from this root.
|
|
157
|
+
* You can also assign a new value to this property to replace the entire tree, as long as the new value is one of the types allowed at the root.
|
|
158
|
+
*
|
|
159
|
+
* Example: Read the current root with \`const currentRoot = context.root;\`
|
|
160
|
+
*${rootTypes.length > 0 ? ` Example: Replace the entire root with \`context.root = context.create.${getFriendlyName(rootTypes[0] ?? oob())}({ });\`\n *` : ""}/
|
|
161
|
+
root: ReadableField<TSchema>;
|
|
162
|
+
${createDocs}
|
|
163
|
+
${isDocs}
|
|
164
|
+
/**
|
|
165
|
+
* Returns the parent object/array/map of the given object/array/map, if there is one.
|
|
166
|
+
* @returns The parent node, or \`undefined\` if the node is the root or is not in the tree.
|
|
167
|
+
* @remarks
|
|
168
|
+
* Example: Get the parent with \`const parent = context.parent(child);\`
|
|
169
|
+
*/
|
|
170
|
+
parent(child: TreeData): TreeData | undefined;
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* Returns the property key or index of the given object/array/map within its parent.
|
|
174
|
+
* @returns A string key if the child is in an object or map, or a numeric index if the child is in an array.
|
|
175
|
+
*
|
|
176
|
+
* Example: \`const key = context.key(child);\`
|
|
177
|
+
*/
|
|
178
|
+
key(child: TreeData): string | number;
|
|
179
|
+
}
|
|
180
|
+
\`\`\``;
|
|
181
|
+
|
|
71
182
|
const helperMethodExplanation = details.hasHelperMethods
|
|
72
183
|
? `Manipulating the data using the APIs described below is allowed, but when possible ALWAYS prefer to use any application helper methods exposed on the schema TypeScript types if the goal can be accomplished that way.
|
|
73
184
|
It will often not be possible to fully accomplish the goal using those helpers. When this is the case, mutate the objects as normal, taking into account the following guidance.`
|
|
74
185
|
: "";
|
|
75
186
|
|
|
76
|
-
const builderExplanation =
|
|
77
|
-
exampleObjectName === undefined
|
|
78
|
-
? ""
|
|
79
|
-
: `When constructing new objects, you should wrap them in the appropriate builder function rather than simply making a javascript object.
|
|
80
|
-
The builders are available on the \`create\` property on the context object and are named according to the type that they create.
|
|
81
|
-
For example:
|
|
82
|
-
|
|
83
|
-
\`\`\`javascript
|
|
84
|
-
// This creates a new ${exampleObjectName} object:
|
|
85
|
-
const ${communize(exampleObjectName)} = context.create.${exampleObjectName}({ /* ...properties... */ });
|
|
86
|
-
// Don't do this:
|
|
87
|
-
// const ${communize(exampleObjectName)} = { /* ...properties... */ };
|
|
88
|
-
\`\`\`\n\n`;
|
|
89
|
-
|
|
90
187
|
const reinsertionExplanation = `Once non-primitive data has been removed from the tree (e.g. replaced via assignment, or removed from an array), that data cannot be re-inserted into the tree.
|
|
91
188
|
Instead, it must be deep cloned and recreated.
|
|
92
189
|
${
|
|
@@ -160,7 +257,6 @@ ${getTreeMapNodeDocumentation(mapInterfaceName)}
|
|
|
160
257
|
|
|
161
258
|
`;
|
|
162
259
|
|
|
163
|
-
const rootTypes = normalizeFieldSchema(schema).allowedTypeSet;
|
|
164
260
|
const editing = `If the user asks you to edit the tree, you should author a snippet of JavaScript code to accomplish the user-specified goal, following the instructions for editing detailed below.
|
|
165
261
|
You must use the "${editToolName}" tool to run the generated code.
|
|
166
262
|
After editing the tree, review the latest state of the tree to see if it satisfies the user's request.
|
|
@@ -173,14 +269,18 @@ If the user asks you to edit the document, you will write a snippet of JavaScrip
|
|
|
173
269
|
The snippet may be synchronous or asynchronous (i.e. it may \`await\` functions if necessary).
|
|
174
270
|
The snippet has a \`context\` variable in its scope.
|
|
175
271
|
This \`context\` variable holds the current state of the tree in the \`root\` property.
|
|
176
|
-
You may mutate any part of
|
|
177
|
-
You may also set the \`root\` property of the context to be an entirely new value as long as it is one of the types allowed at the root of the tree (\`${
|
|
272
|
+
You may mutate any part of this tree as necessary, taking into account the caveats around${hasArrays ? ` arrays${hasMaps ? " and" : ""}` : ""}${hasMaps ? " maps" : ""} detailed below.
|
|
273
|
+
You may also set the \`root\` property of the context to be an entirely new value as long as it is one of the types allowed at the root of the tree (\`${rootTypeUnion}\`).
|
|
274
|
+
You should also use the \`context\` object to create new data to insert into the tree, using the builder functions available on the \`create\` property.
|
|
275
|
+
There are other additional helper functions available on the \`context\` object to help you analyze the tree.
|
|
276
|
+
Here is the definition of the \`Context\` interface:
|
|
277
|
+
${context}
|
|
178
278
|
${helperMethodExplanation}
|
|
179
279
|
${hasArrays ? arrayEditing : ""}${hasMaps ? mapEditing : ""}#### Additional Notes
|
|
180
280
|
|
|
181
281
|
Before outputting the edit function, you should check that it is valid according to both the application tree's schema and any restrictions of the editing APIs described above.
|
|
182
282
|
|
|
183
|
-
${
|
|
283
|
+
${reinsertionExplanation}
|
|
184
284
|
|
|
185
285
|
Finally, double check that the edits would accomplish the user's request (if it is possible).
|
|
186
286
|
|