@fairspec/agent 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/LICENSE.md +9 -0
  2. package/README.md +3 -0
  3. package/build/actions/tableSchema/asHtml.d.ts +4 -0
  4. package/build/actions/tableSchema/asHtml.js +82 -0
  5. package/build/actions/tableSchema/asHtml.spec.d.ts +1 -0
  6. package/build/actions/tableSchema/asHtml.spec.js +356 -0
  7. package/build/actions/tableSchema/asMarkdown.d.ts +4 -0
  8. package/build/actions/tableSchema/asMarkdown.js +65 -0
  9. package/build/actions/tableSchema/asMarkdown.spec.d.ts +1 -0
  10. package/build/actions/tableSchema/asMarkdown.spec.js +133 -0
  11. package/build/document/Document.d.ts +2 -0
  12. package/build/document/Document.js +2 -0
  13. package/build/document/index.d.ts +3 -0
  14. package/build/document/index.js +3 -0
  15. package/build/document/types/Base.d.ts +3 -0
  16. package/build/document/types/Base.js +2 -0
  17. package/build/document/types/Json.d.ts +5 -0
  18. package/build/document/types/Json.js +2 -0
  19. package/build/document/validate.d.ts +5 -0
  20. package/build/document/validate.js +23 -0
  21. package/build/document/validate.spec.d.ts +1 -0
  22. package/build/document/validate.spec.js +71 -0
  23. package/build/index.d.ts +1 -0
  24. package/build/index.js +2 -0
  25. package/build/package.json +39 -0
  26. package/build/plugin.d.ts +6 -0
  27. package/build/plugin.js +15 -0
  28. package/build/schema/convert/toHtml.d.ts +4 -0
  29. package/build/schema/convert/toHtml.js +107 -0
  30. package/build/schema/convert/toHtml.spec.d.ts +1 -0
  31. package/build/schema/convert/toHtml.spec.js +432 -0
  32. package/build/schema/convert/toMarkdown.d.ts +4 -0
  33. package/build/schema/convert/toMarkdown.js +75 -0
  34. package/build/schema/convert/toMarkdown.spec.d.ts +1 -0
  35. package/build/schema/convert/toMarkdown.spec.js +137 -0
  36. package/build/schema/index.d.ts +2 -0
  37. package/build/schema/index.js +3 -0
  38. package/build/server.d.ts +2 -0
  39. package/build/server.js +29 -0
  40. package/build/tableSchema/convert/toHtml.d.ts +4 -0
  41. package/build/tableSchema/convert/toHtml.js +80 -0
  42. package/build/tableSchema/convert/toHtml.spec.d.ts +1 -0
  43. package/build/tableSchema/convert/toHtml.spec.js +375 -0
  44. package/build/tableSchema/convert/toMarkdown.d.ts +4 -0
  45. package/build/tableSchema/convert/toMarkdown.js +57 -0
  46. package/build/tableSchema/convert/toMarkdown.spec.d.ts +1 -0
  47. package/build/tableSchema/convert/toMarkdown.spec.js +141 -0
  48. package/build/tableSchema/index.d.ts +2 -0
  49. package/build/tableSchema/index.js +3 -0
  50. package/build/tools/data/validate.d.ts +971 -0
  51. package/build/tools/data/validate.js +15 -0
  52. package/build/tools/data/validate.spec.d.ts +1 -0
  53. package/build/tools/data/validate.spec.js +228 -0
  54. package/build/tools/dataSchema/infer.d.ts +797 -0
  55. package/build/tools/dataSchema/infer.js +15 -0
  56. package/build/tools/dataSchema/infer.spec.d.ts +1 -0
  57. package/build/tools/dataSchema/infer.spec.js +215 -0
  58. package/build/tools/dataSchema/validate.d.ts +177 -0
  59. package/build/tools/dataSchema/validate.js +17 -0
  60. package/build/tools/dataSchema/validate.spec.d.ts +1 -0
  61. package/build/tools/dataSchema/validate.spec.js +148 -0
  62. package/build/tools/dataset/infer.d.ts +1985 -0
  63. package/build/tools/dataset/infer.js +15 -0
  64. package/build/tools/dataset/infer.spec.d.ts +1 -0
  65. package/build/tools/dataset/infer.spec.js +181 -0
  66. package/build/tools/dataset/validate.d.ts +1168 -0
  67. package/build/tools/dataset/validate.js +17 -0
  68. package/build/tools/dataset/validate.spec.d.ts +1 -0
  69. package/build/tools/dataset/validate.spec.js +212 -0
  70. package/build/tools/dialect/infer.d.ts +889 -0
  71. package/build/tools/dialect/infer.js +16 -0
  72. package/build/tools/dialect/infer.spec.d.ts +1 -0
  73. package/build/tools/dialect/infer.spec.js +138 -0
  74. package/build/tools/table/query.d.ts +798 -0
  75. package/build/tools/table/query.js +24 -0
  76. package/build/tools/table/query.spec.d.ts +1 -0
  77. package/build/tools/table/query.spec.js +138 -0
  78. package/build/tools/table/validate.d.ts +999 -0
  79. package/build/tools/table/validate.js +16 -0
  80. package/build/tools/table/validate.spec.d.ts +1 -0
  81. package/build/tools/table/validate.spec.js +106 -0
  82. package/build/tools/tableSchema/infer.d.ts +1316 -0
  83. package/build/tools/tableSchema/infer.js +16 -0
  84. package/build/tools/tableSchema/infer.spec.d.ts +1 -0
  85. package/build/tools/tableSchema/infer.spec.js +152 -0
  86. package/build/tools/tableSchema/validate.d.ts +177 -0
  87. package/build/tools/tableSchema/validate.js +17 -0
  88. package/build/tools/tableSchema/validate.spec.d.ts +1 -0
  89. package/build/tools/tableSchema/validate.spec.js +121 -0
  90. package/package.json +39 -0
@@ -0,0 +1,24 @@
1
+ import { loadTable, queryTable, Resource } from "@fairspec/library";
2
+ import { createTool } from "@mastra/core/tools";
3
+ import { z } from "zod";
4
+ export const queryTableTool = createTool({
5
+ id: "query-table",
6
+ description: "Query a table using SQL. Loads the table, executes the SQL query, and returns the results as an array of records.",
7
+ inputSchema: z.object({
8
+ resource: Resource.describe("The table resource to query"),
9
+ query: z
10
+ .string()
11
+ .describe("SQL query to execute (use 'self' as table name)"),
12
+ }),
13
+ outputSchema: z.array(z.record(z.string(), z.unknown())),
14
+ execute: async (input) => {
15
+ const table = await loadTable(input.resource, {});
16
+ if (!table) {
17
+ throw new Error("Could not load table");
18
+ }
19
+ const lazyFrame = queryTable(table, input.query);
20
+ const frame = await lazyFrame.collect();
21
+ return frame.toRecords();
22
+ },
23
+ });
24
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi90b29scy90YWJsZS9xdWVyeS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBRSxRQUFRLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQTtBQUNuRSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sb0JBQW9CLENBQUE7QUFDL0MsT0FBTyxFQUFFLENBQUMsRUFBRSxNQUFNLEtBQUssQ0FBQTtBQUV2QixNQUFNLENBQUMsTUFBTSxjQUFjLEdBQUcsVUFBVSxDQUFDO0lBQ3ZDLEVBQUUsRUFBRSxhQUFhO0lBQ2pCLFdBQVcsRUFDVCxtSEFBbUg7SUFDckgsV0FBVyxFQUFFLENBQUMsQ0FBQyxNQUFNLENBQUM7UUFDcEIsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRLENBQUMsNkJBQTZCLENBQUM7UUFDMUQsS0FBSyxFQUFFLENBQUM7YUFDTCxNQUFNLEVBQUU7YUFDUixRQUFRLENBQUMsaURBQWlELENBQUM7S0FDL0QsQ0FBQztJQUNGLFlBQVksRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDO0lBQ3hELE9BQU8sRUFBRSxLQUFLLEVBQUMsS0FBSyxFQUFDLEVBQUU7UUFDckIsTUFBTSxLQUFLLEdBQUcsTUFBTSxTQUFTLENBQUMsS0FBSyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQTtRQUNqRCxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDWCxNQUFNLElBQUksS0FBSyxDQUFDLHNCQUFzQixDQUFDLENBQUE7UUFDekMsQ0FBQztRQUVELE1BQU0sU0FBUyxHQUFHLFVBQVUsQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ2hELE1BQU0sS0FBSyxHQUFHLE1BQU0sU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFBO1FBQ3ZDLE9BQU8sS0FBSyxDQUFDLFNBQVMsRUFBRSxDQUFBO0lBQzFCLENBQUM7Q0FDRixDQUFDLENBQUEiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBsb2FkVGFibGUsIHF1ZXJ5VGFibGUsIFJlc291cmNlIH0gZnJvbSBcIkBmYWlyc3BlYy9saWJyYXJ5XCJcbmltcG9ydCB7IGNyZWF0ZVRvb2wgfSBmcm9tIFwiQG1hc3RyYS9jb3JlL3Rvb2xzXCJcbmltcG9ydCB7IHogfSBmcm9tIFwiem9kXCJcblxuZXhwb3J0IGNvbnN0IHF1ZXJ5VGFibGVUb29sID0gY3JlYXRlVG9vbCh7XG4gIGlkOiBcInF1ZXJ5LXRhYmxlXCIsXG4gIGRlc2NyaXB0aW9uOlxuICAgIFwiUXVlcnkgYSB0YWJsZSB1c2luZyBTUUwuIExvYWRzIHRoZSB0YWJsZSwgZXhlY3V0ZXMgdGhlIFNRTCBxdWVyeSwgYW5kIHJldHVybnMgdGhlIHJlc3VsdHMgYXMgYW4gYXJyYXkgb2YgcmVjb3Jkcy5cIixcbiAgaW5wdXRTY2hlbWE6IHoub2JqZWN0KHtcbiAgICByZXNvdXJjZTogUmVzb3VyY2UuZGVzY3JpYmUoXCJUaGUgdGFibGUgcmVzb3VyY2UgdG8gcXVlcnlcIiksXG4gICAgcXVlcnk6IHpcbiAgICAgIC5zdHJpbmcoKVxuICAgICAgLmRlc2NyaWJlKFwiU1FMIHF1ZXJ5IHRvIGV4ZWN1dGUgKHVzZSAnc2VsZicgYXMgdGFibGUgbmFtZSlcIiksXG4gIH0pLFxuICBvdXRwdXRTY2hlbWE6IHouYXJyYXkoei5yZWNvcmQoei5zdHJpbmcoKSwgei51bmtub3duKCkpKSxcbiAgZXhlY3V0ZTogYXN5bmMgaW5wdXQgPT4ge1xuICAgIGNvbnN0IHRhYmxlID0gYXdhaXQgbG9hZFRhYmxlKGlucHV0LnJlc291cmNlLCB7fSlcbiAgICBpZiAoIXRhYmxlKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXCJDb3VsZCBub3QgbG9hZCB0YWJsZVwiKVxuICAgIH1cblxuICAgIGNvbnN0IGxhenlGcmFtZSA9IHF1ZXJ5VGFibGUodGFibGUsIGlucHV0LnF1ZXJ5KVxuICAgIGNvbnN0IGZyYW1lID0gYXdhaXQgbGF6eUZyYW1lLmNvbGxlY3QoKVxuICAgIHJldHVybiBmcmFtZS50b1JlY29yZHMoKVxuICB9LFxufSlcbiJdfQ==
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,138 @@
1
+ import { writeTempFile } from "@fairspec/library";
2
+ import { describe, expect, it } from "vitest";
3
+ import { queryTableTool } from "./query.js";
4
+ describe("queryTableTool", () => {
5
+ it("validates tool structure", () => {
6
+ expect(queryTableTool.id).toBe("query-table");
7
+ expect(queryTableTool.description).toBeTruthy();
8
+ expect(queryTableTool.inputSchema).toBeTruthy();
9
+ expect(queryTableTool.outputSchema).toBeTruthy();
10
+ expect(queryTableTool.execute).toBeTypeOf("function");
11
+ });
12
+ it("queries table with SELECT statement", async () => {
13
+ const csvContent = "id,name,age\n1,alice,25\n2,bob,30\n3,carol,28";
14
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
15
+ const resource = { data: csvPath, dialect: { format: "csv" } };
16
+ const result = await queryTableTool.execute?.({
17
+ resource,
18
+ query: "SELECT * FROM self WHERE age > 25",
19
+ }, {});
20
+ expect.assert(result);
21
+ expect.assert(!("error" in result));
22
+ expect(Array.isArray(result)).toBe(true);
23
+ expect(result.length).toBe(2);
24
+ expect(result).toContainEqual({ id: 2, name: "bob", age: 30 });
25
+ expect(result).toContainEqual({ id: 3, name: "carol", age: 28 });
26
+ });
27
+ it("queries table with column selection", async () => {
28
+ const csvContent = "id,name,age,city\n1,alice,25,NYC\n2,bob,30,LA\n3,carol,28,SF";
29
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
30
+ const resource = { data: csvPath, dialect: { format: "csv" } };
31
+ const result = await queryTableTool.execute?.({
32
+ resource,
33
+ query: "SELECT name, city FROM self",
34
+ }, {});
35
+ expect.assert(result);
36
+ expect.assert(!("error" in result));
37
+ expect(Array.isArray(result)).toBe(true);
38
+ expect(result.length).toBe(3);
39
+ expect(result[0]).toHaveProperty("name");
40
+ expect(result[0]).toHaveProperty("city");
41
+ expect(result[0]).not.toHaveProperty("id");
42
+ expect(result[0]).not.toHaveProperty("age");
43
+ });
44
+ it("queries table with ORDER BY clause", async () => {
45
+ const csvContent = "id,name,score\n1,alice,85\n2,bob,90\n3,carol,88";
46
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
47
+ const resource = { data: csvPath, dialect: { format: "csv" } };
48
+ const result = await queryTableTool.execute?.({
49
+ resource,
50
+ query: "SELECT * FROM self ORDER BY score DESC",
51
+ }, {});
52
+ expect.assert(result);
53
+ expect.assert(!("error" in result));
54
+ expect(Array.isArray(result)).toBe(true);
55
+ expect(result.length).toBe(3);
56
+ expect(result[0]).toMatchObject({ name: "bob", score: 90 });
57
+ expect(result[1]).toMatchObject({ name: "carol", score: 88 });
58
+ expect(result[2]).toMatchObject({ name: "alice", score: 85 });
59
+ });
60
+ it("queries table with aggregation", async () => {
61
+ const csvContent = "id,name,score\n1,alice,85\n2,bob,90\n3,carol,88";
62
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
63
+ const resource = { data: csvPath, dialect: { format: "csv" } };
64
+ const result = await queryTableTool.execute?.({
65
+ resource,
66
+ query: "SELECT COUNT(*) as count, AVG(score) as avg_score FROM self",
67
+ }, {});
68
+ expect.assert(result);
69
+ expect.assert(!("error" in result));
70
+ expect(Array.isArray(result)).toBe(true);
71
+ expect(result.length).toBe(1);
72
+ expect(result[0]).toHaveProperty("count");
73
+ expect(result[0]).toHaveProperty("avg_score");
74
+ });
75
+ it("queries table with WHERE and LIMIT", async () => {
76
+ const csvContent = "id,name,age\n1,alice,25\n2,bob,30\n3,carol,28\n4,dave,35\n5,eve,22";
77
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
78
+ const resource = { data: csvPath, dialect: { format: "csv" } };
79
+ const result = await queryTableTool.execute?.({
80
+ resource,
81
+ query: "SELECT * FROM self WHERE age >= 25 ORDER BY age LIMIT 2",
82
+ }, {});
83
+ expect.assert(result);
84
+ expect.assert(!("error" in result));
85
+ expect(Array.isArray(result)).toBe(true);
86
+ expect(result.length).toBe(2);
87
+ });
88
+ it("queries inline data", async () => {
89
+ const resource = {
90
+ data: [
91
+ { id: 1, name: "alice", score: 85 },
92
+ { id: 2, name: "bob", score: 90 },
93
+ { id: 3, name: "carol", score: 88 },
94
+ ],
95
+ };
96
+ const result = await queryTableTool.execute?.({
97
+ resource,
98
+ query: "SELECT name, score FROM self WHERE score > 85",
99
+ }, {});
100
+ expect.assert(result);
101
+ expect.assert(!("error" in result));
102
+ expect(Array.isArray(result)).toBe(true);
103
+ expect(result.length).toBe(2);
104
+ expect(result).toContainEqual({ name: "bob", score: 90 });
105
+ expect(result).toContainEqual({ name: "carol", score: 88 });
106
+ });
107
+ it("queries with JOIN operations", async () => {
108
+ const resource = {
109
+ data: [
110
+ { id: 1, name: "alice", dept_id: 10 },
111
+ { id: 2, name: "bob", dept_id: 20 },
112
+ ],
113
+ };
114
+ const result = await queryTableTool.execute?.({
115
+ resource,
116
+ query: "SELECT * FROM self WHERE dept_id = 10",
117
+ }, {});
118
+ expect.assert(result);
119
+ expect.assert(!("error" in result));
120
+ expect(Array.isArray(result)).toBe(true);
121
+ expect(result.length).toBe(1);
122
+ expect(result[0]).toMatchObject({ name: "alice", dept_id: 10 });
123
+ });
124
+ it("returns all records when querying without filters", async () => {
125
+ const csvContent = "id,name\n1,alice\n2,bob\n3,carol";
126
+ const csvPath = await writeTempFile(csvContent, { format: "csv" });
127
+ const resource = { data: csvPath, dialect: { format: "csv" } };
128
+ const result = await queryTableTool.execute?.({
129
+ resource,
130
+ query: "SELECT * FROM self",
131
+ }, {});
132
+ expect.assert(result);
133
+ expect.assert(!("error" in result));
134
+ expect(Array.isArray(result)).toBe(true);
135
+ expect(result.length).toBe(3);
136
+ });
137
+ });
138
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicXVlcnkuc3BlYy5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3Rvb2xzL3RhYmxlL3F1ZXJ5LnNwZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQ0EsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLG1CQUFtQixDQUFBO0FBQ2pELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxNQUFNLFFBQVEsQ0FBQTtBQUM3QyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sWUFBWSxDQUFBO0FBRTNDLFFBQVEsQ0FBQyxnQkFBZ0IsRUFBRSxHQUFHLEVBQUU7SUFDOUIsRUFBRSxDQUFDLDBCQUEwQixFQUFFLEdBQUcsRUFBRTtRQUNsQyxNQUFNLENBQUMsY0FBYyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQTtRQUM3QyxNQUFNLENBQUMsY0FBYyxDQUFDLFdBQVcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxDQUFBO1FBQy9DLE1BQU0sQ0FBQyxjQUFjLENBQUMsV0FBVyxDQUFDLENBQUMsVUFBVSxFQUFFLENBQUE7UUFDL0MsTUFBTSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxVQUFVLEVBQUUsQ0FBQTtRQUNoRCxNQUFNLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxDQUFDLFVBQVUsQ0FBQyxVQUFVLENBQUMsQ0FBQTtJQUN2RCxDQUFDLENBQUMsQ0FBQTtJQUVGLEVBQUUsQ0FBQyxxQ0FBcUMsRUFBRSxLQUFLLElBQUksRUFBRTtRQUNuRCxNQUFNLFVBQVUsR0FBRywrQ0FBK0MsQ0FBQTtRQUNsRSxNQUFNLE9BQU8sR0FBRyxNQUFNLGFBQWEsQ0FBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtRQUNsRSxNQUFNLFFBQVEsR0FBYSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFB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LENBQUMsQ0FBQyxDQUFBO1FBQzdCLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxhQUFhLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLE9BQU8sRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFBO0lBQ2pFLENBQUMsQ0FBQyxDQUFBO0lBRUYsRUFBRSxDQUFDLG1EQUFtRCxFQUFFLEtBQUssSUFBSSxFQUFFO1FBQ2pFLE1BQU0sVUFBVSxHQUFHLGtDQUFrQyxDQUFBO1FBQ3JELE1BQU0sT0FBTyxHQUFHLE1BQU0sYUFBYSxDQUFDLFVBQVUsRUFBRSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBQ2xFLE1BQU0sUUFBUSxHQUFhLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLEVBQUUsQ0FBQTtRQUV4RSxNQUFNLE1BQU0sR0FBRyxNQUFNLGNBQWMsQ0FBQyxPQUFPLEVBQUUsQ0FDM0M7WUFDRSxRQUFRO1lBQ1IsS0FBSyxFQUFFLG9CQUFvQjtTQUM1QixFQUNELEVBQUUsQ0FDSCxDQUFBO1FBRUQsTUFBTSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUNyQixNQUFNLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxPQUFPLElBQUksTUFBTSxDQUFDLENBQUMsQ0FBQTtRQUVuQyxNQUFNLENBQUMsS0FBSyxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUN4QyxNQUFNLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUMvQixDQUFDLENBQUMsQ0FBQTtBQUNKLENBQUMsQ0FBQyxDQUFBIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHR5cGUgeyBSZXNvdXJjZSB9IGZyb20gXCJAZmFpcnNwZWMvbGlicmFyeVwiXG5pbXBvcnQgeyB3cml0ZVRlbXBGaWxlIH0gZnJvbSBcIkBmYWlyc3BlYy9saWJyYXJ5XCJcbmltcG9ydCB7IGRlc2NyaWJlLCBleHBlY3QsIGl0IH0gZnJvbSBcInZpdGVzdFwiXG5pbXBvcnQgeyBxdWVyeVRhYmxlVG9vbCB9IGZyb20gXCIuL3F1ZXJ5LnRzXCJcblxuZGVzY3JpYmUoXCJxdWVyeVRhYmxlVG9vbFwiLCAoKSA9PiB7XG4gIGl0KFwidmFsaWRhdGVzIHRvb2wgc3RydWN0dXJlXCIsICgpID0+IHtcbiAgICBleHBlY3QocXVlcnlUYWJsZVRvb2wuaWQpLnRvQmUoXCJxdWVyeS10YWJsZVwiKVxuICAgIGV4cGVjdChxdWVyeVRhYmxlVG9vbC5kZXNjcmlwdGlvbikudG9CZVRydXRoeSgpXG4gICAgZXhwZWN0KHF1ZXJ5VGFibGVUb29sLmlucHV0U2NoZW1hKS50b0JlVHJ1dGh5KClcbiAgICBleHBlY3QocXVlcnlUYWJsZVRvb2wub3V0cHV0U2NoZW1hKS50b0JlVHJ1dGh5KClcbiAgICBleHBlY3QocXVlcnlUYWJsZVRvb2wuZXhlY3V0ZSkudG9CZVR5cGVPZihcImZ1bmN0aW9uXCIpXG4gIH0pXG5cbiAgaXQoXCJxdWVyaWVzIHRhYmxlIHdpdGggU0VMRUNUIHN0YXRlbWVudFwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3N2Q29udGVudCA9IFwiaWQsbmFtZSxhZ2VcXG4xLGFsaWNlLDI1XFxuMixib2IsMzBcXG4zLGNhcm9sLDI4XCJcbiAgICBjb25zdCBjc3ZQYXRoID0gYXdhaXQgd3JpdGVUZW1wRmlsZShjc3ZDb250ZW50LCB7IGZvcm1hdDogXCJjc3ZcIiB9KVxuICAgIGNvbnN0IHJlc291cmNlOiBSZXNvdXJjZSA9IHsgZGF0YTogY3N2UGF0aCwgZGlhbGVjdDogeyBmb3JtYXQ6IFwiY3N2XCIgfSB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBxdWVyeVRhYmxlVG9vbC5leGVjdXRlPy4oXG4gICAgICB7XG4gICAgICAgIHJlc291cmNlLFxuICAgICAgICBxdWVyeTogXCJTRUxFQ1QgKiBGUk9NIHNlbGYgV0hFUkUgYWdlID4gMjVcIixcbiAgICAgIH0sXG4gICAgICB7fSxcbiAgICApXG5cbiAgICBleHBlY3QuYXNzZXJ0KHJlc3VsdClcbiAgICBleHBlY3QuYXNzZXJ0KCEoXCJlcnJvclwiIGluIHJlc3VsdCkpXG5cbiAgICBleHBlY3QoQXJyYXkuaXNBcnJheShyZXN1bHQpKS50b0JlKHRydWUpXG4gICAgZXhwZWN0KHJlc3VsdC5sZW5ndGgpLnRvQmUoMilcbiAgICBleHBlY3QocmVzdWx0KS50b0NvbnRhaW5FcXVhbCh7IGlkOiAyLCBuYW1lOiBcImJvYlwiLCBhZ2U6IDMwIH0pXG4gICAgZXhwZWN0KHJlc3VsdCkudG9Db250YWluRXF1YWwoeyBpZDogMywgbmFtZTogXCJjYXJvbFwiLCBhZ2U6IDI4IH0pXG4gIH0pXG5cbiAgaXQoXCJxdWVyaWVzIHRhYmxlIHdpdGggY29sdW1uIHNlbGVjdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3N2Q29udGVudCA9XG4gICAgICBcImlkLG5hbWUsYWdlLGNpdHlcXG4xLGFsaWNlLDI1LE5ZQ1xcbjIsYm9iLDMwLExBXFxuMyxjYXJvbCwyOCxTRlwiXG4gICAgY29uc3QgY3N2UGF0aCA9IGF3YWl0IHdyaXRlVGVtcEZpbGUoY3N2Q29udGVudCwgeyBmb3JtYXQ6IFwiY3N2XCIgfSlcbiAgICBjb25zdCByZXNvdXJjZTogUmVzb3VyY2UgPSB7IGRhdGE6IGNzdlBhdGgsIGRpYWxlY3Q6IHsgZm9ybWF0OiBcImNzdlwiIH0gfVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgcXVlcnlUYWJsZVRvb2wuZXhlY3V0ZT8uKFxuICAgICAge1xuICAgICAgICByZXNvdXJjZSxcbiAgICAgICAgcXVlcnk6IFwiU0VMRUNUIG5hbWUsIGNpdHkgRlJPTSBzZWxmXCIsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KEFycmF5LmlzQXJyYXkocmVzdWx0KSkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChyZXN1bHQubGVuZ3RoKS50b0JlKDMpXG4gICAgZXhwZWN0KHJlc3VsdFswXSkudG9IYXZlUHJvcGVydHkoXCJuYW1lXCIpXG4gICAgZXhwZWN0KHJlc3VsdFswXSkudG9IYXZlUHJvcGVydHkoXCJjaXR5XCIpXG4gICAgZXhwZWN0KHJlc3VsdFswXSkubm90LnRvSGF2ZVByb3BlcnR5KFwiaWRcIilcbiAgICBleHBlY3QocmVzdWx0WzBdKS5ub3QudG9IYXZlUHJvcGVydHkoXCJhZ2VcIilcbiAgfSlcblxuICBpdChcInF1ZXJpZXMgdGFibGUgd2l0aCBPUkRFUiBCWSBjbGF1c2VcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IGNzdkNvbnRlbnQgPSBcImlkLG5hbWUsc2NvcmVcXG4xLGFsaWNlLDg1XFxuMixib2IsOTBcXG4zLGNhcm9sLDg4XCJcbiAgICBjb25zdCBjc3ZQYXRoID0gYXdhaXQgd3JpdGVUZW1wRmlsZShjc3ZDb250ZW50LCB7IGZvcm1hdDogXCJjc3ZcIiB9KVxuICAgIGNvbnN0IHJlc291cmNlOiBSZXNvdXJjZSA9IHsgZGF0YTogY3N2UGF0aCwgZGlhbGVjdDogeyBmb3JtYXQ6IFwiY3N2XCIgfSB9XG5cbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBxdWVyeVRhYmxlVG9vbC5leGVjdXRlPy4oXG4gICAgICB7XG4gICAgICAgIHJlc291cmNlLFxuICAgICAgICBxdWVyeTogXCJTRUxFQ1QgKiBGUk9NIHNlbGYgT1JERVIgQlkgc2NvcmUgREVTQ1wiLFxuICAgICAgfSxcbiAgICAgIHt9LFxuICAgIClcblxuICAgIGV4cGVjdC5hc3NlcnQocmVzdWx0KVxuICAgIGV4cGVjdC5hc3NlcnQoIShcImVycm9yXCIgaW4gcmVzdWx0KSlcblxuICAgIGV4cGVjdChBcnJheS5pc0FycmF5KHJlc3VsdCkpLnRvQmUodHJ1ZSlcbiAgICBleHBlY3QocmVzdWx0Lmxlbmd0aCkudG9CZSgzKVxuICAgIGV4cGVjdChyZXN1bHRbMF0pLnRvTWF0Y2hPYmplY3QoeyBuYW1lOiBcImJvYlwiLCBzY29yZTogOTAgfSlcbiAgICBleHBlY3QocmVzdWx0WzFdKS50b01hdGNoT2JqZWN0KHsgbmFtZTogXCJjYXJvbFwiLCBzY29yZTogODggfSlcbiAgICBleHBlY3QocmVzdWx0WzJdKS50b01hdGNoT2JqZWN0KHsgbmFtZTogXCJhbGljZVwiLCBzY29yZTogODUgfSlcbiAgfSlcblxuICBpdChcInF1ZXJpZXMgdGFibGUgd2l0aCBhZ2dyZWdhdGlvblwiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3N2Q29udGVudCA9IFwiaWQsbmFtZSxzY29yZVxcbjEsYWxpY2UsODVcXG4yLGJvYiw5MFxcbjMsY2Fyb2wsODhcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQsIHsgZm9ybWF0OiBcImNzdlwiIH0pXG4gICAgY29uc3QgcmVzb3VyY2U6IFJlc291cmNlID0geyBkYXRhOiBjc3ZQYXRoLCBkaWFsZWN0OiB7IGZvcm1hdDogXCJjc3ZcIiB9IH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5VGFibGVUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgIHF1ZXJ5OiBcIlNFTEVDVCBDT1VOVCgqKSBhcyBjb3VudCwgQVZHKHNjb3JlKSBhcyBhdmdfc2NvcmUgRlJPTSBzZWxmXCIsXG4gICAgICB9LFxuICAgICAge30sXG4gICAgKVxuXG4gICAgZXhwZWN0LmFzc2VydChyZXN1bHQpXG4gICAgZXhwZWN0LmFzc2VydCghKFwiZXJyb3JcIiBpbiByZXN1bHQpKVxuXG4gICAgZXhwZWN0KEFycmF5LmlzQXJyYXkocmVzdWx0KSkudG9CZSh0cnVlKVxuICAgIGV4cGVjdChyZXN1bHQubGVuZ3RoKS50b0JlKDEpXG4gICAgZXhwZWN0KHJlc3VsdFswXSkudG9IYXZlUHJvcGVydHkoXCJjb3VudFwiKVxuICAgIGV4cGVjdChyZXN1bHRbMF0pLnRvSGF2ZVByb3BlcnR5KFwiYXZnX3Njb3JlXCIpXG4gIH0pXG5cbiAgaXQoXCJxdWVyaWVzIHRhYmxlIHdpdGggV0hFUkUgYW5kIExJTUlUXCIsIGFzeW5jICgpID0+IHtcbiAgICBjb25zdCBjc3ZDb250ZW50ID1cbiAgICAgIFwiaWQsbmFtZSxhZ2VcXG4xLGFsaWNlLDI1XFxuMixib2IsMzBcXG4zLGNhcm9sLDI4XFxuNCxkYXZlLDM1XFxuNSxldmUsMjJcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQsIHsgZm9ybWF0OiBcImNzdlwiIH0pXG4gICAgY29uc3QgcmVzb3VyY2U6IFJlc291cmNlID0geyBkYXRhOiBjc3ZQYXRoLCBkaWFsZWN0OiB7IGZvcm1hdDogXCJjc3ZcIiB9IH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5VGFibGVUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgIHF1ZXJ5OiBcIlNFTEVDVCAqIEZST00gc2VsZiBXSEVSRSBhZ2UgPj0gMjUgT1JERVIgQlkgYWdlIExJTUlUIDJcIixcbiAgICAgIH0sXG4gICAgICB7fSxcbiAgICApXG5cbiAgICBleHBlY3QuYXNzZXJ0KHJlc3VsdClcbiAgICBleHBlY3QuYXNzZXJ0KCEoXCJlcnJvclwiIGluIHJlc3VsdCkpXG5cbiAgICBleHBlY3QoQXJyYXkuaXNBcnJheShyZXN1bHQpKS50b0JlKHRydWUpXG4gICAgZXhwZWN0KHJlc3VsdC5sZW5ndGgpLnRvQmUoMilcbiAgfSlcblxuICBpdChcInF1ZXJpZXMgaW5saW5lIGRhdGFcIiwgYXN5bmMgKCkgPT4ge1xuICAgIGNvbnN0IHJlc291cmNlOiBSZXNvdXJjZSA9IHtcbiAgICAgIGRhdGE6IFtcbiAgICAgICAgeyBpZDogMSwgbmFtZTogXCJhbGljZVwiLCBzY29yZTogODUgfSxcbiAgICAgICAgeyBpZDogMiwgbmFtZTogXCJib2JcIiwgc2NvcmU6IDkwIH0sXG4gICAgICAgIHsgaWQ6IDMsIG5hbWU6IFwiY2Fyb2xcIiwgc2NvcmU6IDg4IH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5VGFibGVUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgIHF1ZXJ5OiBcIlNFTEVDVCBuYW1lLCBzY29yZSBGUk9NIHNlbGYgV0hFUkUgc2NvcmUgPiA4NVwiLFxuICAgICAgfSxcbiAgICAgIHt9LFxuICAgIClcblxuICAgIGV4cGVjdC5hc3NlcnQocmVzdWx0KVxuICAgIGV4cGVjdC5hc3NlcnQoIShcImVycm9yXCIgaW4gcmVzdWx0KSlcblxuICAgIGV4cGVjdChBcnJheS5pc0FycmF5KHJlc3VsdCkpLnRvQmUodHJ1ZSlcbiAgICBleHBlY3QocmVzdWx0Lmxlbmd0aCkudG9CZSgyKVxuICAgIGV4cGVjdChyZXN1bHQpLnRvQ29udGFpbkVxdWFsKHsgbmFtZTogXCJib2JcIiwgc2NvcmU6IDkwIH0pXG4gICAgZXhwZWN0KHJlc3VsdCkudG9Db250YWluRXF1YWwoeyBuYW1lOiBcImNhcm9sXCIsIHNjb3JlOiA4OCB9KVxuICB9KVxuXG4gIGl0KFwicXVlcmllcyB3aXRoIEpPSU4gb3BlcmF0aW9uc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgcmVzb3VyY2U6IFJlc291cmNlID0ge1xuICAgICAgZGF0YTogW1xuICAgICAgICB7IGlkOiAxLCBuYW1lOiBcImFsaWNlXCIsIGRlcHRfaWQ6IDEwIH0sXG4gICAgICAgIHsgaWQ6IDIsIG5hbWU6IFwiYm9iXCIsIGRlcHRfaWQ6IDIwIH0sXG4gICAgICBdLFxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5VGFibGVUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgIHF1ZXJ5OiBcIlNFTEVDVCAqIEZST00gc2VsZiBXSEVSRSBkZXB0X2lkID0gMTBcIixcbiAgICAgIH0sXG4gICAgICB7fSxcbiAgICApXG5cbiAgICBleHBlY3QuYXNzZXJ0KHJlc3VsdClcbiAgICBleHBlY3QuYXNzZXJ0KCEoXCJlcnJvclwiIGluIHJlc3VsdCkpXG5cbiAgICBleHBlY3QoQXJyYXkuaXNBcnJheShyZXN1bHQpKS50b0JlKHRydWUpXG4gICAgZXhwZWN0KHJlc3VsdC5sZW5ndGgpLnRvQmUoMSlcbiAgICBleHBlY3QocmVzdWx0WzBdKS50b01hdGNoT2JqZWN0KHsgbmFtZTogXCJhbGljZVwiLCBkZXB0X2lkOiAxMCB9KVxuICB9KVxuXG4gIGl0KFwicmV0dXJucyBhbGwgcmVjb3JkcyB3aGVuIHF1ZXJ5aW5nIHdpdGhvdXQgZmlsdGVyc1wiLCBhc3luYyAoKSA9PiB7XG4gICAgY29uc3QgY3N2Q29udGVudCA9IFwiaWQsbmFtZVxcbjEsYWxpY2VcXG4yLGJvYlxcbjMsY2Fyb2xcIlxuICAgIGNvbnN0IGNzdlBhdGggPSBhd2FpdCB3cml0ZVRlbXBGaWxlKGNzdkNvbnRlbnQsIHsgZm9ybWF0OiBcImNzdlwiIH0pXG4gICAgY29uc3QgcmVzb3VyY2U6IFJlc291cmNlID0geyBkYXRhOiBjc3ZQYXRoLCBkaWFsZWN0OiB7IGZvcm1hdDogXCJjc3ZcIiB9IH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHF1ZXJ5VGFibGVUb29sLmV4ZWN1dGU/LihcbiAgICAgIHtcbiAgICAgICAgcmVzb3VyY2UsXG4gICAgICAgIHF1ZXJ5OiBcIlNFTEVDVCAqIEZST00gc2VsZlwiLFxuICAgICAgfSxcbiAgICAgIHt9LFxuICAgIClcblxuICAgIGV4cGVjdC5hc3NlcnQocmVzdWx0KVxuICAgIGV4cGVjdC5hc3NlcnQoIShcImVycm9yXCIgaW4gcmVzdWx0KSlcblxuICAgIGV4cGVjdChBcnJheS5pc0FycmF5KHJlc3VsdCkpLnRvQmUodHJ1ZSlcbiAgICBleHBlY3QocmVzdWx0Lmxlbmd0aCkudG9CZSgzKVxuICB9KVxufSlcbiJdfQ==