@fluidframework/tree-agent 2.63.0-359461 → 2.63.0-359962
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 +3 -24
- package/dist/agent.d.ts +0 -3
- package/dist/agent.d.ts.map +1 -1
- package/dist/agent.js +21 -49
- package/dist/agent.js.map +1 -1
- package/dist/alpha.d.ts +0 -2
- package/dist/api.d.ts +19 -7
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -4
- package/dist/index.js.map +1 -1
- package/dist/prompt.d.ts.map +1 -1
- package/dist/prompt.js +15 -17
- package/dist/prompt.js.map +1 -1
- package/dist/utils.d.ts +4 -0
- package/dist/utils.d.ts.map +1 -1
- package/dist/utils.js +16 -1
- package/dist/utils.js.map +1 -1
- package/lib/agent.d.ts +0 -3
- package/lib/agent.d.ts.map +1 -1
- package/lib/agent.js +22 -50
- package/lib/agent.js.map +1 -1
- package/lib/alpha.d.ts +0 -2
- package/lib/api.d.ts +19 -7
- package/lib/api.d.ts.map +1 -1
- package/lib/api.js.map +1 -1
- package/lib/index.d.ts +0 -1
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +0 -1
- package/lib/index.js.map +1 -1
- package/lib/prompt.d.ts.map +1 -1
- package/lib/prompt.js +15 -17
- package/lib/prompt.js.map +1 -1
- package/lib/utils.d.ts +4 -0
- package/lib/utils.d.ts.map +1 -1
- package/lib/utils.js +14 -0
- package/lib/utils.js.map +1 -1
- package/package.json +11 -12
- package/src/agent.ts +29 -61
- package/src/api.ts +20 -12
- package/src/index.ts +0 -1
- package/src/prompt.ts +15 -17
- package/src/utils.ts +14 -0
- package/dist/functionParsing.d.ts +0 -13
- package/dist/functionParsing.d.ts.map +0 -1
- package/dist/functionParsing.js +0 -215
- package/dist/functionParsing.js.map +0 -1
- package/dist/langchain.d.ts +0 -43
- package/dist/langchain.d.ts.map +0 -1
- package/dist/langchain.js +0 -90
- package/dist/langchain.js.map +0 -1
- package/lib/functionParsing.d.ts +0 -13
- package/lib/functionParsing.d.ts.map +0 -1
- package/lib/functionParsing.js +0 -210
- package/lib/functionParsing.js.map +0 -1
- package/lib/langchain.d.ts +0 -43
- package/lib/langchain.d.ts.map +0 -1
- package/lib/langchain.js +0 -84
- package/lib/langchain.js.map +0 -1
- package/src/functionParsing.ts +0 -268
- package/src/langchain.ts +0 -146
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@fluidframework/tree-agent",
|
|
3
|
-
"version": "2.63.0-
|
|
3
|
+
"version": "2.63.0-359962",
|
|
4
4
|
"description": "Experimental package to simplify integrating AI into Fluid-based applications",
|
|
5
5
|
"homepage": "https://fluidframework.com",
|
|
6
6
|
"repository": {
|
|
@@ -70,28 +70,26 @@
|
|
|
70
70
|
},
|
|
71
71
|
"dependencies": {
|
|
72
72
|
"@anthropic-ai/sdk": "^0.39.0",
|
|
73
|
-
"@fluidframework/core-utils": "2.63.0-
|
|
74
|
-
"@fluidframework/runtime-utils": "2.63.0-
|
|
75
|
-
"@fluidframework/telemetry-utils": "2.63.0-
|
|
76
|
-
"@fluidframework/tree": "2.63.0-
|
|
77
|
-
"@langchain/core": "^0.3.66",
|
|
78
|
-
"acorn": "^8.15.0",
|
|
79
|
-
"langchain": "^0.3.30",
|
|
73
|
+
"@fluidframework/core-utils": "2.63.0-359962",
|
|
74
|
+
"@fluidframework/runtime-utils": "2.63.0-359962",
|
|
75
|
+
"@fluidframework/telemetry-utils": "2.63.0-359962",
|
|
76
|
+
"@fluidframework/tree": "2.63.0-359962",
|
|
80
77
|
"uuid": "^11.1.0",
|
|
81
78
|
"zod": "^3.25.32"
|
|
82
79
|
},
|
|
83
80
|
"devDependencies": {
|
|
84
81
|
"@arethetypeswrong/cli": "^0.17.1",
|
|
85
82
|
"@biomejs/biome": "~1.9.3",
|
|
86
|
-
"@fluid-internal/mocha-test-setup": "2.63.0-
|
|
83
|
+
"@fluid-internal/mocha-test-setup": "2.63.0-359962",
|
|
87
84
|
"@fluid-tools/build-cli": "^0.58.3",
|
|
88
85
|
"@fluidframework/build-common": "^2.0.3",
|
|
89
86
|
"@fluidframework/build-tools": "^0.58.3",
|
|
90
87
|
"@fluidframework/eslint-config-fluid": "^6.0.0",
|
|
91
|
-
"@fluidframework/id-compressor": "2.63.0-
|
|
92
|
-
"@fluidframework/runtime-utils": "2.63.0-
|
|
93
|
-
"@fluidframework/test-runtime-utils": "2.63.0-
|
|
88
|
+
"@fluidframework/id-compressor": "2.63.0-359962",
|
|
89
|
+
"@fluidframework/runtime-utils": "2.63.0-359962",
|
|
90
|
+
"@fluidframework/test-runtime-utils": "2.63.0-359962",
|
|
94
91
|
"@langchain/anthropic": "^0.3.24",
|
|
92
|
+
"@langchain/core": "^0.3.78",
|
|
95
93
|
"@langchain/google-genai": "^0.2.16",
|
|
96
94
|
"@langchain/openai": "^0.6.12",
|
|
97
95
|
"@microsoft/api-extractor": "7.52.11",
|
|
@@ -108,6 +106,7 @@
|
|
|
108
106
|
"mocha-multi-reporters": "^1.5.1",
|
|
109
107
|
"prettier": "~3.0.3",
|
|
110
108
|
"rimraf": "^4.4.0",
|
|
109
|
+
"ses": "^1.14.0",
|
|
111
110
|
"typescript": "~5.4.5"
|
|
112
111
|
},
|
|
113
112
|
"fluidBuild": {
|
package/src/agent.ts
CHANGED
|
@@ -17,14 +17,7 @@ import type {
|
|
|
17
17
|
} from "@fluidframework/tree/alpha";
|
|
18
18
|
import { ObjectNodeSchema, Tree } from "@fluidframework/tree/alpha";
|
|
19
19
|
|
|
20
|
-
import type {
|
|
21
|
-
SharedTreeChatModel,
|
|
22
|
-
EditFunction,
|
|
23
|
-
EditResult,
|
|
24
|
-
SemanticAgentOptions,
|
|
25
|
-
Logger,
|
|
26
|
-
} from "./api.js";
|
|
27
|
-
import { findInvocableFunctionName, stripExportSyntax } from "./functionParsing.js";
|
|
20
|
+
import type { SharedTreeChatModel, EditResult, SemanticAgentOptions, Logger } from "./api.js";
|
|
28
21
|
import { getPrompt, stringifyTree } from "./prompt.js";
|
|
29
22
|
import { Subtree } from "./subtree.js";
|
|
30
23
|
import {
|
|
@@ -33,6 +26,7 @@ import {
|
|
|
33
26
|
llmDefault,
|
|
34
27
|
type TreeView,
|
|
35
28
|
findNamedSchemas,
|
|
29
|
+
toErrorString,
|
|
36
30
|
} from "./utils.js";
|
|
37
31
|
|
|
38
32
|
/**
|
|
@@ -41,11 +35,6 @@ import {
|
|
|
41
35
|
*/
|
|
42
36
|
const defaultMaxSequentialEdits = 20;
|
|
43
37
|
|
|
44
|
-
/**
|
|
45
|
-
* The name of the parameter passed to the edit function.
|
|
46
|
-
*/
|
|
47
|
-
const paramsName = "params";
|
|
48
|
-
|
|
49
38
|
/**
|
|
50
39
|
* An agent that uses a {@link SharedTreeChatModel} to interact with a SharedTree.
|
|
51
40
|
* @remarks This class forwards user queries to the chat model, and handles the application of any edits to the tree that the model requests.
|
|
@@ -123,7 +112,7 @@ export class SharedTreeSemanticAgent<TSchema extends ImplicitFieldSchema> {
|
|
|
123
112
|
let editCount = 0;
|
|
124
113
|
let editFailed = false;
|
|
125
114
|
const { editToolName } = this.client;
|
|
126
|
-
const edit = async (
|
|
115
|
+
const edit = async (editCode: string): Promise<EditResult> => {
|
|
127
116
|
if (editToolName === undefined) {
|
|
128
117
|
return {
|
|
129
118
|
type: "disabledError",
|
|
@@ -147,8 +136,9 @@ export class SharedTreeSemanticAgent<TSchema extends ImplicitFieldSchema> {
|
|
|
147
136
|
|
|
148
137
|
const editResult = await applyTreeFunction(
|
|
149
138
|
queryTree,
|
|
150
|
-
|
|
151
|
-
this.options?.
|
|
139
|
+
editCode,
|
|
140
|
+
this.options?.validateEdit ?? defaultValidateEdit,
|
|
141
|
+
this.options?.executeEdit ?? defaultExecuteEdit,
|
|
152
142
|
this.options?.logger,
|
|
153
143
|
);
|
|
154
144
|
|
|
@@ -208,18 +198,22 @@ function constructTreeNode(schema: TreeNodeSchema, value: FactoryContentObject):
|
|
|
208
198
|
*/
|
|
209
199
|
async function applyTreeFunction<TSchema extends ImplicitFieldSchema>(
|
|
210
200
|
tree: Subtree<TSchema>,
|
|
211
|
-
|
|
212
|
-
|
|
201
|
+
editCode: string,
|
|
202
|
+
validateEdit: Required<SemanticAgentOptions>["validateEdit"],
|
|
203
|
+
executeEdit: Required<SemanticAgentOptions>["executeEdit"],
|
|
213
204
|
logger: Logger | undefined,
|
|
214
205
|
): Promise<EditResult> {
|
|
215
206
|
logger?.log(`### Editing Tool Invoked\n\n`);
|
|
216
|
-
logger?.log(`#### Generated Code\n\n\`\`\`javascript\n${
|
|
207
|
+
logger?.log(`#### Generated Code\n\n\`\`\`javascript\n${editCode}\n\`\`\`\n\n`);
|
|
217
208
|
|
|
218
|
-
|
|
209
|
+
try {
|
|
210
|
+
await validateEdit(editCode);
|
|
211
|
+
} catch (error: unknown) {
|
|
219
212
|
logger?.log(`#### Code Validation Failed\n\n`);
|
|
213
|
+
logger?.log(`\`\`\`JSON\n${toErrorString(error)}\n\`\`\`\n\n`);
|
|
220
214
|
return {
|
|
221
215
|
type: "validationError",
|
|
222
|
-
message:
|
|
216
|
+
message: `The generated code did not pass validation: ${toErrorString(error)}`,
|
|
223
217
|
};
|
|
224
218
|
}
|
|
225
219
|
|
|
@@ -232,7 +226,7 @@ async function applyTreeFunction<TSchema extends ImplicitFieldSchema>(
|
|
|
232
226
|
|
|
233
227
|
// Fork a branch to edit. If the edit fails or produces an error, we discard this branch, otherwise we merge it.
|
|
234
228
|
const editTree = tree.fork();
|
|
235
|
-
const
|
|
229
|
+
const context = {
|
|
236
230
|
get root(): ReadableField<TSchema> {
|
|
237
231
|
return editTree.field;
|
|
238
232
|
},
|
|
@@ -242,34 +236,15 @@ async function applyTreeFunction<TSchema extends ImplicitFieldSchema>(
|
|
|
242
236
|
create,
|
|
243
237
|
};
|
|
244
238
|
|
|
245
|
-
let editFunction: EditFunction<TSchema>;
|
|
246
|
-
if (typeof fn === "string") {
|
|
247
|
-
try {
|
|
248
|
-
editFunction = processLlmCode(fn);
|
|
249
|
-
} catch (error) {
|
|
250
|
-
logger?.log(`#### Error\n\n`);
|
|
251
|
-
const errorMessage = error instanceof Error ? error.message : JSON.stringify(error);
|
|
252
|
-
logger?.log(`\`\`\`JSON\n${errorMessage}\n\`\`\`\n\n`);
|
|
253
|
-
editTree.branch.dispose();
|
|
254
|
-
return {
|
|
255
|
-
type: "compileError",
|
|
256
|
-
message: `The supplied JavaScript function is not valid: ${errorMessage}`,
|
|
257
|
-
};
|
|
258
|
-
}
|
|
259
|
-
} else {
|
|
260
|
-
editFunction = fn;
|
|
261
|
-
}
|
|
262
|
-
|
|
263
239
|
try {
|
|
264
|
-
await
|
|
240
|
+
await executeEdit(context, editCode);
|
|
265
241
|
} catch (error: unknown) {
|
|
266
242
|
logger?.log(`#### Error\n\n`);
|
|
267
|
-
|
|
268
|
-
logger?.log(`\`\`\`JSON\n${errorMessage}\n\`\`\`\n\n`);
|
|
243
|
+
logger?.log(`\`\`\`JSON\n${toErrorString(error)}\n\`\`\`\n\n`);
|
|
269
244
|
editTree.branch.dispose();
|
|
270
245
|
return {
|
|
271
|
-
type: "
|
|
272
|
-
message: `Running the
|
|
246
|
+
type: "executionError",
|
|
247
|
+
message: `Running the generated code produced an error. The state of the tree will be reset to its previous state as it was before the code ran. Please try again. Here is the error: ${toErrorString(error)}`,
|
|
273
248
|
};
|
|
274
249
|
}
|
|
275
250
|
|
|
@@ -278,24 +253,17 @@ async function applyTreeFunction<TSchema extends ImplicitFieldSchema>(
|
|
|
278
253
|
logger?.log(`${`\`\`\`JSON\n${stringifyTree(tree.field)}\n\`\`\``}\n\n`);
|
|
279
254
|
return {
|
|
280
255
|
type: "success",
|
|
281
|
-
message: `After running the
|
|
256
|
+
message: `After running the code, the new state of the tree is:\n\n\`\`\`JSON\n${stringifyTree(tree.field)}\n\`\`\``,
|
|
282
257
|
};
|
|
283
258
|
}
|
|
284
259
|
|
|
285
|
-
|
|
286
|
-
code: string,
|
|
287
|
-
): EditFunction<TSchema> {
|
|
288
|
-
const functionName = findInvocableFunctionName(code);
|
|
289
|
-
if (functionName === undefined) {
|
|
290
|
-
throw new Error("Generated code does not contain an invokable function");
|
|
291
|
-
}
|
|
260
|
+
const defaultValidateEdit: Required<SemanticAgentOptions>["validateEdit"] = () => {};
|
|
292
261
|
|
|
293
|
-
|
|
262
|
+
const defaultExecuteEdit: Required<SemanticAgentOptions>["executeEdit"] = async (
|
|
263
|
+
context,
|
|
264
|
+
code,
|
|
265
|
+
) => {
|
|
294
266
|
// eslint-disable-next-line no-new-func, @typescript-eslint/no-implied-eval
|
|
295
|
-
const fn = new Function(
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Finds the name of the first invocable function in the given code.
|
|
301
|
-
*/
|
|
267
|
+
const fn = new Function("context", code);
|
|
268
|
+
await fn(context);
|
|
269
|
+
};
|
package/src/api.ts
CHANGED
|
@@ -4,11 +4,8 @@
|
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
import type { ImplicitFieldSchema, TreeNode } from "@fluidframework/tree";
|
|
7
|
-
import type { FactoryContentObject, ReadableField } from "@fluidframework/tree/alpha";
|
|
8
|
-
|
|
9
7
|
// This is used for doc links
|
|
10
|
-
|
|
11
|
-
import type { SharedTreeSemanticAgent } from "./agent.js";
|
|
8
|
+
import type { FactoryContentObject, ReadableField } from "@fluidframework/tree/alpha";
|
|
12
9
|
|
|
13
10
|
/**
|
|
14
11
|
* Logger interface for logging events from a {@link SharedTreeSemanticAgent}.
|
|
@@ -31,10 +28,22 @@ export interface SemanticAgentOptions {
|
|
|
31
28
|
*/
|
|
32
29
|
domainHints?: string;
|
|
33
30
|
/**
|
|
34
|
-
* Validates any generated JavaScript created by the {@link SharedTreeChatModel.editToolName | model's editing tool}
|
|
35
|
-
* @remarks
|
|
31
|
+
* Validates any generated JavaScript created by the {@link SharedTreeChatModel.editToolName | model's editing tool}.
|
|
32
|
+
* @remarks This happens before the code is executed - execution can be intercepted by using the {@link SemanticAgentOptions.executeEdit | executeEdit} callback.
|
|
33
|
+
* @param code - The generated JavaScript code as a string.
|
|
34
|
+
* @throws If the code is invalid, this function should throw an error with a human-readable message describing why it is invalid.
|
|
35
|
+
*/
|
|
36
|
+
validateEdit?: (code: string) => void | Promise<void>;
|
|
37
|
+
/**
|
|
38
|
+
* Evaluates/runs any generated JavaScript created by the {@link SharedTreeChatModel.editToolName | model's editing tool}.
|
|
39
|
+
* @remarks This happens only after the code has been successfully validated by the optional {@link SemanticAgentOptions.validateEdit | validateEdit} function.
|
|
40
|
+
* @param context - An object that must be provided to the generated code as a variable named "context" in its top-level scope.
|
|
41
|
+
* @param code - The generated JavaScript code as a string.
|
|
42
|
+
* @throws If an error is thrown while executing the code, it will be caught and the message will be forwarded to the model for debugging.
|
|
43
|
+
* @remarks If this function is not provided, the generated code will be executed using a simple `eval` call, which may not provide sufficient security guarantees for some environments.
|
|
44
|
+
* Use a library such as SES to provide a more secure implementation - see `@fluidframework/tree-agent-ses` for a drop-in implementation.
|
|
36
45
|
*/
|
|
37
|
-
|
|
46
|
+
executeEdit?: (context: Record<string, unknown>, code: string) => void | Promise<void>;
|
|
38
47
|
/**
|
|
39
48
|
* The maximum number of sequential edits the LLM can make before we assume it's stuck in a loop.
|
|
40
49
|
*/
|
|
@@ -50,9 +59,8 @@ export interface SemanticAgentOptions {
|
|
|
50
59
|
* @remarks
|
|
51
60
|
* - `success`: The edit was successfully applied.
|
|
52
61
|
* - `disabledError`: The model is not allowed to edit the tree (i.e. {@link SharedTreeChatModel.editToolName} was not provided).
|
|
53
|
-
* - `validationError`: The provided JavaScript did not pass the optional {@link SemanticAgentOptions.
|
|
54
|
-
* - `
|
|
55
|
-
* - `runtimeError`: An error was thrown while executing the provided JavaScript.
|
|
62
|
+
* - `validationError`: The provided JavaScript did not pass the optional {@link SemanticAgentOptions.validateEdit} function.
|
|
63
|
+
* - `executionError`: An error was thrown while parsing or executing the provided JavaScript.
|
|
56
64
|
* - `tooManyEditsError`: The {@link SharedTreeChatQuery.edit} function has been called more than the number of times specified by {@link SemanticAgentOptions.maximumSequentialEdits} for the same message.
|
|
57
65
|
* - `expiredError`: The {@link SharedTreeChatQuery.edit} function was called after the issuing query has already completed.
|
|
58
66
|
* @alpha
|
|
@@ -62,8 +70,7 @@ export interface EditResult {
|
|
|
62
70
|
| "success"
|
|
63
71
|
| "disabledError"
|
|
64
72
|
| "validationError"
|
|
65
|
-
| "
|
|
66
|
-
| "runtimeError"
|
|
73
|
+
| "executionError"
|
|
67
74
|
| "tooManyEditsError"
|
|
68
75
|
| "expiredError";
|
|
69
76
|
|
|
@@ -107,6 +114,7 @@ export interface SharedTreeChatQuery {
|
|
|
107
114
|
/**
|
|
108
115
|
* A plugin interface that handles queries from a {@link SharedTreeSemanticAgent}.
|
|
109
116
|
* @remarks This wraps an underlying communication with an LLM and receives all necessary {@link SharedTreeChatModel.appendContext | context} from the {@link SharedTreeSemanticAgent | agent} for the LLM to properly analyze and edit the tree.
|
|
117
|
+
* See `@fluidframework/tree-agent-langchain` for a drop-in implementation based on the LangChain library.
|
|
110
118
|
* @alpha
|
|
111
119
|
*/
|
|
112
120
|
export interface SharedTreeChatModel {
|
package/src/index.ts
CHANGED
package/src/prompt.ts
CHANGED
|
@@ -69,7 +69,7 @@ export function getPrompt<TRoot extends ImplicitFieldSchema>(args: {
|
|
|
69
69
|
const details: SchemaDetails = { hasHelperMethods: false };
|
|
70
70
|
const typescriptSchemaTypes = getZodSchemaAsTypeScript(domainTypes, details);
|
|
71
71
|
const helperMethodExplanation = details.hasHelperMethods
|
|
72
|
-
? `Manipulating the data using the APIs described below is allowed, but when possible ALWAYS prefer to use
|
|
72
|
+
? `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
73
|
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
74
|
: "";
|
|
75
75
|
|
|
@@ -77,16 +77,14 @@ It will often not be possible to fully accomplish the goal using those helpers.
|
|
|
77
77
|
exampleObjectName === undefined
|
|
78
78
|
? ""
|
|
79
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
|
|
80
|
+
The builders are available on the \`create\` property on the context object and are named according to the type that they create.
|
|
81
81
|
For example:
|
|
82
82
|
|
|
83
83
|
\`\`\`javascript
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
// const ${communize(exampleObjectName)} = { /* ...properties... */ };
|
|
89
|
-
}
|
|
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... */ };
|
|
90
88
|
\`\`\`\n\n`;
|
|
91
89
|
|
|
92
90
|
const arrayEditing = `#### Editing Arrays
|
|
@@ -120,20 +118,20 @@ ${getTreeMapNodeDocumentation(mapInterfaceName)}
|
|
|
120
118
|
`;
|
|
121
119
|
|
|
122
120
|
const rootTypes = normalizeFieldSchema(schema).allowedTypeSet;
|
|
123
|
-
const editing = `If the user asks you to edit the tree, you should author a JavaScript
|
|
124
|
-
You must use the "${editToolName}" tool to
|
|
121
|
+
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.
|
|
122
|
+
You must use the "${editToolName}" tool to run the generated code.
|
|
125
123
|
After editing the tree, review the latest state of the tree to see if it satisfies the user's request.
|
|
126
124
|
If it does not, or if you receive an error, you may try again with a different approach.
|
|
127
125
|
Once the tree is in the desired state, you should inform the user that the request has been completed.
|
|
128
126
|
|
|
129
127
|
### Editing
|
|
130
128
|
|
|
131
|
-
If the user asks you to edit the document, you will write a JavaScript
|
|
132
|
-
The
|
|
133
|
-
The
|
|
134
|
-
This \`
|
|
135
|
-
You may mutate any part of the tree as necessary, taking into account the caveats around arrays and maps detailed below.
|
|
136
|
-
You may also set the \`root\` property to be an entirely new value as long as it is one of the types allowed at the root of the tree (\`${Array.from(rootTypes.values(), (t) => getFriendlyName(t)).join(" | ")}\`).
|
|
129
|
+
If the user asks you to edit the document, you will write a snippet of JavaScript code that mutates the data in-place to achieve the user's goal.
|
|
130
|
+
The snippet may be synchronous or asynchronous (i.e. it may \`await\` functions if necessary).
|
|
131
|
+
The snippet has a \`context\` variable in its scope.
|
|
132
|
+
This \`context\` variable holds the current state of the tree in the \`root\` property.
|
|
133
|
+
You may mutate any part of the root tree as necessary, taking into account the caveats around${hasArrays ? ` arrays${hasMaps ? " and" : ""}` : ""}${hasMaps ? " maps" : ""} detailed below.
|
|
134
|
+
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 (\`${Array.from(rootTypes.values(), (t) => getFriendlyName(t)).join(" | ")}\`).
|
|
137
135
|
${helperMethodExplanation}
|
|
138
136
|
|
|
139
137
|
${hasArrays ? arrayEditing : ""}${hasMaps ? mapEditing : ""}#### Additional Notes
|
|
@@ -163,7 +161,7 @@ ${
|
|
|
163
161
|
? ""
|
|
164
162
|
: `\nThe application supplied the following additional instructions: ${domainHints}`
|
|
165
163
|
}
|
|
166
|
-
The current state of
|
|
164
|
+
The current state of \`context.root\` (a \`${field === undefined ? "undefined" : getFriendlyName(Tree.schema(field))}\`) is:
|
|
167
165
|
|
|
168
166
|
\`\`\`JSON
|
|
169
167
|
${stringified}
|
package/src/utils.ts
CHANGED
|
@@ -619,3 +619,17 @@ export function findNamedSchemas(
|
|
|
619
619
|
export function communize(str: string): string {
|
|
620
620
|
return str.charAt(0).toLowerCase() + str.slice(1);
|
|
621
621
|
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Stringify an unknown error value
|
|
625
|
+
*/
|
|
626
|
+
export function toErrorString(error: unknown): string {
|
|
627
|
+
if (error instanceof Error) {
|
|
628
|
+
return error.message;
|
|
629
|
+
}
|
|
630
|
+
try {
|
|
631
|
+
return JSON.stringify(error);
|
|
632
|
+
} catch {
|
|
633
|
+
return String(error);
|
|
634
|
+
}
|
|
635
|
+
}
|
|
@@ -1,13 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
3
|
-
* Licensed under the MIT License.
|
|
4
|
-
*/
|
|
5
|
-
/**
|
|
6
|
-
* Finds the name of the first invocable function in the given code string.
|
|
7
|
-
*/
|
|
8
|
-
export declare function findInvocableFunctionName(code: string): string | undefined;
|
|
9
|
-
/**
|
|
10
|
-
* Removes top-level export syntax so that the provided code can execute in a classic script context.
|
|
11
|
-
*/
|
|
12
|
-
export declare function stripExportSyntax(code: string): string;
|
|
13
|
-
//# sourceMappingURL=functionParsing.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"functionParsing.d.ts","sourceRoot":"","sources":["../src/functionParsing.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAsBH;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAc1E;AAED;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CA0DtD"}
|
package/dist/functionParsing.js
DELETED
|
@@ -1,215 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/*!
|
|
3
|
-
* Copyright (c) Microsoft Corporation and contributors. All rights reserved.
|
|
4
|
-
* Licensed under the MIT License.
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.stripExportSyntax = exports.findInvocableFunctionName = void 0;
|
|
8
|
-
/* eslint-disable @rushstack/no-new-null */
|
|
9
|
-
const acorn_1 = require("acorn");
|
|
10
|
-
/**
|
|
11
|
-
* Finds the name of the first invocable function in the given code string.
|
|
12
|
-
*/
|
|
13
|
-
function findInvocableFunctionName(code) {
|
|
14
|
-
const program = parseProgram(code);
|
|
15
|
-
if (program === undefined) {
|
|
16
|
-
return undefined;
|
|
17
|
-
}
|
|
18
|
-
for (const node of program.body) {
|
|
19
|
-
const name = getNameFromTopLevelNode(node);
|
|
20
|
-
if (name !== undefined) {
|
|
21
|
-
return name;
|
|
22
|
-
}
|
|
23
|
-
}
|
|
24
|
-
return undefined;
|
|
25
|
-
}
|
|
26
|
-
exports.findInvocableFunctionName = findInvocableFunctionName;
|
|
27
|
-
/**
|
|
28
|
-
* Removes top-level export syntax so that the provided code can execute in a classic script context.
|
|
29
|
-
*/
|
|
30
|
-
function stripExportSyntax(code) {
|
|
31
|
-
const program = parseProgram(code);
|
|
32
|
-
if (program === undefined) {
|
|
33
|
-
return code;
|
|
34
|
-
}
|
|
35
|
-
const replacements = [];
|
|
36
|
-
for (const node of program.body) {
|
|
37
|
-
switch (node.type) {
|
|
38
|
-
case "ExportNamedDeclaration": {
|
|
39
|
-
if (node.declaration !== undefined && node.declaration !== null) {
|
|
40
|
-
replacements.push({
|
|
41
|
-
start: node.start,
|
|
42
|
-
end: node.declaration.start,
|
|
43
|
-
replacement: "",
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
else {
|
|
47
|
-
replacements.push({ start: node.start, end: node.end, replacement: "" });
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
}
|
|
51
|
-
case "ExportDefaultDeclaration": {
|
|
52
|
-
const { declaration, start, end } = node;
|
|
53
|
-
if (declaration.type === "FunctionDeclaration" ||
|
|
54
|
-
declaration.type === "FunctionExpression") {
|
|
55
|
-
replacements.push({
|
|
56
|
-
start,
|
|
57
|
-
end: declaration.start,
|
|
58
|
-
replacement: "",
|
|
59
|
-
});
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
replacements.push({ start, end, replacement: "" });
|
|
63
|
-
}
|
|
64
|
-
break;
|
|
65
|
-
}
|
|
66
|
-
case "ExportAllDeclaration": {
|
|
67
|
-
replacements.push({ start: node.start, end: node.end, replacement: "" });
|
|
68
|
-
break;
|
|
69
|
-
}
|
|
70
|
-
// No default
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
if (replacements.length === 0) {
|
|
74
|
-
return code;
|
|
75
|
-
}
|
|
76
|
-
replacements.sort((a, b) => b.start - a.start);
|
|
77
|
-
let sanitized = code;
|
|
78
|
-
for (const { start, end, replacement } of replacements) {
|
|
79
|
-
sanitized = `${sanitized.slice(0, start)}${replacement}${sanitized.slice(end)}`;
|
|
80
|
-
}
|
|
81
|
-
return sanitized;
|
|
82
|
-
}
|
|
83
|
-
exports.stripExportSyntax = stripExportSyntax;
|
|
84
|
-
function parseProgram(code) {
|
|
85
|
-
try {
|
|
86
|
-
return (0, acorn_1.parse)(code, {
|
|
87
|
-
ecmaVersion: "latest",
|
|
88
|
-
sourceType: "module",
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
catch {
|
|
92
|
-
try {
|
|
93
|
-
return (0, acorn_1.parse)(code, {
|
|
94
|
-
ecmaVersion: "latest",
|
|
95
|
-
sourceType: "script",
|
|
96
|
-
allowReturnOutsideFunction: true,
|
|
97
|
-
allowAwaitOutsideFunction: true,
|
|
98
|
-
allowSuperOutsideMethod: true,
|
|
99
|
-
});
|
|
100
|
-
}
|
|
101
|
-
catch {
|
|
102
|
-
return undefined;
|
|
103
|
-
}
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
function getNameFromTopLevelNode(node) {
|
|
107
|
-
switch (node.type) {
|
|
108
|
-
case "FunctionDeclaration": {
|
|
109
|
-
return getFunctionIdentifier(node);
|
|
110
|
-
}
|
|
111
|
-
case "VariableDeclaration": {
|
|
112
|
-
return getNameFromVariableDeclaration(node);
|
|
113
|
-
}
|
|
114
|
-
case "ExpressionStatement": {
|
|
115
|
-
return getNameFromExpression(node.expression);
|
|
116
|
-
}
|
|
117
|
-
case "ExportNamedDeclaration": {
|
|
118
|
-
return getNameFromExportNamed(node);
|
|
119
|
-
}
|
|
120
|
-
case "ExportDefaultDeclaration": {
|
|
121
|
-
return getNameFromExportDefault(node);
|
|
122
|
-
}
|
|
123
|
-
default: {
|
|
124
|
-
return undefined;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
function getNameFromVariableDeclaration(node) {
|
|
129
|
-
for (const declarator of node.declarations) {
|
|
130
|
-
const name = getIdentifierFromPattern(declarator.id);
|
|
131
|
-
if (name === undefined) {
|
|
132
|
-
continue;
|
|
133
|
-
}
|
|
134
|
-
if (isFunctionLikeExpression(declarator.init)) {
|
|
135
|
-
return name;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
return undefined;
|
|
139
|
-
}
|
|
140
|
-
function getNameFromExpression(expression) {
|
|
141
|
-
if (!isAssignmentExpression(expression)) {
|
|
142
|
-
return undefined;
|
|
143
|
-
}
|
|
144
|
-
if (expression.operator !== "=") {
|
|
145
|
-
return undefined;
|
|
146
|
-
}
|
|
147
|
-
const target = getIdentifierFromPattern(expression.left);
|
|
148
|
-
if (target === undefined) {
|
|
149
|
-
return undefined;
|
|
150
|
-
}
|
|
151
|
-
return isFunctionLikeExpression(expression.right) ? target : undefined;
|
|
152
|
-
}
|
|
153
|
-
function getNameFromExportNamed(node) {
|
|
154
|
-
const declaration = node.declaration;
|
|
155
|
-
if (declaration !== undefined && declaration !== null) {
|
|
156
|
-
if (declaration.type === "FunctionDeclaration") {
|
|
157
|
-
const name = getFunctionIdentifier(declaration);
|
|
158
|
-
if (name !== undefined) {
|
|
159
|
-
return name;
|
|
160
|
-
}
|
|
161
|
-
}
|
|
162
|
-
else if (declaration.type === "VariableDeclaration") {
|
|
163
|
-
const name = getNameFromVariableDeclaration(declaration);
|
|
164
|
-
if (name !== undefined) {
|
|
165
|
-
return name;
|
|
166
|
-
}
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (node.source === undefined || node.source === null) {
|
|
170
|
-
for (const specifier of node.specifiers) {
|
|
171
|
-
const localName = getIdentifierName(specifier.local);
|
|
172
|
-
if (localName !== undefined) {
|
|
173
|
-
return localName;
|
|
174
|
-
}
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
return undefined;
|
|
178
|
-
}
|
|
179
|
-
function getNameFromExportDefault(node) {
|
|
180
|
-
const declaration = node.declaration;
|
|
181
|
-
if (declaration.type === "Identifier") {
|
|
182
|
-
return declaration.name;
|
|
183
|
-
}
|
|
184
|
-
if (declaration.type === "FunctionDeclaration" ||
|
|
185
|
-
declaration.type === "FunctionExpression") {
|
|
186
|
-
return getFunctionIdentifier(declaration);
|
|
187
|
-
}
|
|
188
|
-
return undefined;
|
|
189
|
-
}
|
|
190
|
-
function isAssignmentExpression(expression) {
|
|
191
|
-
return expression?.type === "AssignmentExpression";
|
|
192
|
-
}
|
|
193
|
-
function getIdentifierFromPattern(pattern) {
|
|
194
|
-
if (pattern.type === "Identifier") {
|
|
195
|
-
return pattern.name;
|
|
196
|
-
}
|
|
197
|
-
return undefined;
|
|
198
|
-
}
|
|
199
|
-
function isFunctionLikeExpression(expression) {
|
|
200
|
-
return (expression?.type === "FunctionExpression" || expression?.type === "ArrowFunctionExpression");
|
|
201
|
-
}
|
|
202
|
-
function getFunctionIdentifier(fn) {
|
|
203
|
-
const id = fn.id;
|
|
204
|
-
if (id === undefined || id === null) {
|
|
205
|
-
return undefined;
|
|
206
|
-
}
|
|
207
|
-
return id.name;
|
|
208
|
-
}
|
|
209
|
-
function getIdentifierName(node) {
|
|
210
|
-
if (node.type === "Identifier") {
|
|
211
|
-
return node.name;
|
|
212
|
-
}
|
|
213
|
-
return undefined;
|
|
214
|
-
}
|
|
215
|
-
//# sourceMappingURL=functionParsing.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"functionParsing.js","sourceRoot":"","sources":["../src/functionParsing.ts"],"names":[],"mappings":"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","sourcesContent":["/*!\n * Copyright (c) Microsoft Corporation and contributors. All rights reserved.\n * Licensed under the MIT License.\n */\n\n/* eslint-disable @rushstack/no-new-null */\n\nimport { parse } from \"acorn\";\nimport type {\n\tProgram,\n\tStatement,\n\tModuleDeclaration,\n\tVariableDeclaration,\n\tExpression,\n\tAssignmentExpression,\n\tPattern,\n\tIdentifier,\n\tLiteral,\n\tExportNamedDeclaration,\n\tExportDefaultDeclaration,\n\tFunctionDeclaration,\n\tFunctionExpression,\n\tArrowFunctionExpression,\n} from \"acorn\";\n\n/**\n * Finds the name of the first invocable function in the given code string.\n */\nexport function findInvocableFunctionName(code: string): string | undefined {\n\tconst program = parseProgram(code);\n\tif (program === undefined) {\n\t\treturn undefined;\n\t}\n\n\tfor (const node of program.body) {\n\t\tconst name = getNameFromTopLevelNode(node);\n\t\tif (name !== undefined) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\n/**\n * Removes top-level export syntax so that the provided code can execute in a classic script context.\n */\nexport function stripExportSyntax(code: string): string {\n\tconst program = parseProgram(code);\n\tif (program === undefined) {\n\t\treturn code;\n\t}\n\n\tconst replacements: { start: number; end: number; replacement: string }[] = [];\n\tfor (const node of program.body) {\n\t\tswitch (node.type) {\n\t\t\tcase \"ExportNamedDeclaration\": {\n\t\t\t\tif (node.declaration !== undefined && node.declaration !== null) {\n\t\t\t\t\treplacements.push({\n\t\t\t\t\t\tstart: node.start,\n\t\t\t\t\t\tend: node.declaration.start,\n\t\t\t\t\t\treplacement: \"\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\treplacements.push({ start: node.start, end: node.end, replacement: \"\" });\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"ExportDefaultDeclaration\": {\n\t\t\t\tconst { declaration, start, end } = node;\n\t\t\t\tif (\n\t\t\t\t\tdeclaration.type === \"FunctionDeclaration\" ||\n\t\t\t\t\tdeclaration.type === \"FunctionExpression\"\n\t\t\t\t) {\n\t\t\t\t\treplacements.push({\n\t\t\t\t\t\tstart,\n\t\t\t\t\t\tend: declaration.start,\n\t\t\t\t\t\treplacement: \"\",\n\t\t\t\t\t});\n\t\t\t\t} else {\n\t\t\t\t\treplacements.push({ start, end, replacement: \"\" });\n\t\t\t\t}\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\tcase \"ExportAllDeclaration\": {\n\t\t\t\treplacements.push({ start: node.start, end: node.end, replacement: \"\" });\n\n\t\t\t\tbreak;\n\t\t\t}\n\t\t\t// No default\n\t\t}\n\t}\n\n\tif (replacements.length === 0) {\n\t\treturn code;\n\t}\n\n\treplacements.sort((a, b) => b.start - a.start);\n\tlet sanitized = code;\n\tfor (const { start, end, replacement } of replacements) {\n\t\tsanitized = `${sanitized.slice(0, start)}${replacement}${sanitized.slice(end)}`;\n\t}\n\treturn sanitized;\n}\n\ntype TopLevelNode = Statement | ModuleDeclaration;\n\nfunction parseProgram(code: string): Program | undefined {\n\ttry {\n\t\treturn parse(code, {\n\t\t\tecmaVersion: \"latest\",\n\t\t\tsourceType: \"module\",\n\t\t});\n\t} catch {\n\t\ttry {\n\t\t\treturn parse(code, {\n\t\t\t\tecmaVersion: \"latest\",\n\t\t\t\tsourceType: \"script\",\n\t\t\t\tallowReturnOutsideFunction: true,\n\t\t\t\tallowAwaitOutsideFunction: true,\n\t\t\t\tallowSuperOutsideMethod: true,\n\t\t\t});\n\t\t} catch {\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n\nfunction getNameFromTopLevelNode(node: TopLevelNode): string | undefined {\n\tswitch (node.type) {\n\t\tcase \"FunctionDeclaration\": {\n\t\t\treturn getFunctionIdentifier(node);\n\t\t}\n\t\tcase \"VariableDeclaration\": {\n\t\t\treturn getNameFromVariableDeclaration(node);\n\t\t}\n\t\tcase \"ExpressionStatement\": {\n\t\t\treturn getNameFromExpression(node.expression);\n\t\t}\n\t\tcase \"ExportNamedDeclaration\": {\n\t\t\treturn getNameFromExportNamed(node);\n\t\t}\n\t\tcase \"ExportDefaultDeclaration\": {\n\t\t\treturn getNameFromExportDefault(node);\n\t\t}\n\t\tdefault: {\n\t\t\treturn undefined;\n\t\t}\n\t}\n}\n\nfunction getNameFromVariableDeclaration(node: VariableDeclaration): string | undefined {\n\tfor (const declarator of node.declarations) {\n\t\tconst name = getIdentifierFromPattern(declarator.id);\n\t\tif (name === undefined) {\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (isFunctionLikeExpression(declarator.init)) {\n\t\t\treturn name;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction getNameFromExpression(\n\texpression: Expression | Literal | undefined,\n): string | undefined {\n\tif (!isAssignmentExpression(expression)) {\n\t\treturn undefined;\n\t}\n\n\tif (expression.operator !== \"=\") {\n\t\treturn undefined;\n\t}\n\n\tconst target = getIdentifierFromPattern(expression.left);\n\tif (target === undefined) {\n\t\treturn undefined;\n\t}\n\n\treturn isFunctionLikeExpression(expression.right) ? target : undefined;\n}\n\nfunction getNameFromExportNamed(node: ExportNamedDeclaration): string | undefined {\n\tconst declaration = node.declaration;\n\tif (declaration !== undefined && declaration !== null) {\n\t\tif (declaration.type === \"FunctionDeclaration\") {\n\t\t\tconst name = getFunctionIdentifier(declaration);\n\t\t\tif (name !== undefined) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t} else if (declaration.type === \"VariableDeclaration\") {\n\t\t\tconst name = getNameFromVariableDeclaration(declaration);\n\t\t\tif (name !== undefined) {\n\t\t\t\treturn name;\n\t\t\t}\n\t\t}\n\t}\n\n\tif (node.source === undefined || node.source === null) {\n\t\tfor (const specifier of node.specifiers) {\n\t\t\tconst localName = getIdentifierName(specifier.local);\n\t\t\tif (localName !== undefined) {\n\t\t\t\treturn localName;\n\t\t\t}\n\t\t}\n\t}\n\n\treturn undefined;\n}\n\nfunction getNameFromExportDefault(node: ExportDefaultDeclaration): string | undefined {\n\tconst declaration = node.declaration;\n\tif (declaration.type === \"Identifier\") {\n\t\treturn declaration.name;\n\t}\n\n\tif (\n\t\tdeclaration.type === \"FunctionDeclaration\" ||\n\t\tdeclaration.type === \"FunctionExpression\"\n\t) {\n\t\treturn getFunctionIdentifier(declaration);\n\t}\n\n\treturn undefined;\n}\n\nfunction isAssignmentExpression(\n\texpression: Expression | Literal | undefined,\n): expression is AssignmentExpression {\n\treturn expression?.type === \"AssignmentExpression\";\n}\n\nfunction getIdentifierFromPattern(pattern: Pattern): string | undefined {\n\tif (pattern.type === \"Identifier\") {\n\t\treturn pattern.name;\n\t}\n\treturn undefined;\n}\n\nfunction isFunctionLikeExpression(\n\texpression: Expression | null | undefined,\n): expression is FunctionExpression | ArrowFunctionExpression {\n\treturn (\n\t\texpression?.type === \"FunctionExpression\" || expression?.type === \"ArrowFunctionExpression\"\n\t);\n}\n\nfunction getFunctionIdentifier(\n\tfn: FunctionDeclaration | FunctionExpression | { id?: Identifier | null },\n): string | undefined {\n\tconst id = fn.id;\n\tif (id === undefined || id === null) {\n\t\treturn undefined;\n\t}\n\treturn id.name;\n}\n\nfunction getIdentifierName(node: Identifier | Literal): string | undefined {\n\tif (node.type === \"Identifier\") {\n\t\treturn node.name;\n\t}\n\treturn undefined;\n}\n"]}
|